Initialize migration. (#88)
Co-authored-by: defnotken <itsdefnotken@gmail.com> Co-authored-by: cake <admin@cakeandbanana.nl> Reviewed-on: #88 Reviewed-by: cake <cake@noreply.git.lightless-sync.org> Co-authored-by: defnotken <defnotken@noreply.git.lightless-sync.org> Co-committed-by: defnotken <defnotken@noreply.git.lightless-sync.org>
This commit was merged in pull request #88.
This commit is contained in:
@@ -2,6 +2,7 @@ using Dalamud.Bindings.ImGui;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Colors;
|
||||
using Dalamud.Interface.Utility;
|
||||
using Dalamud.Utility;
|
||||
using LightlessSync.API.Dto.Group;
|
||||
using LightlessSync.LightlessConfiguration;
|
||||
using LightlessSync.Services;
|
||||
@@ -21,7 +22,7 @@ namespace LightlessSync.UI
|
||||
private readonly UiSharedService _uiSharedService;
|
||||
private readonly BroadcastScannerService _broadcastScannerService;
|
||||
|
||||
private IReadOnlyList<GroupFullInfoDto> _allSyncshells;
|
||||
private IReadOnlyList<GroupFullInfoDto> _allSyncshells = Array.Empty<GroupFullInfoDto>();
|
||||
private string _userUid = string.Empty;
|
||||
|
||||
private readonly List<(string Label, string? GID, bool IsAvailable)> _syncshellOptions = new();
|
||||
@@ -191,7 +192,7 @@ namespace LightlessSync.UI
|
||||
ImGui.PopStyleVar();
|
||||
|
||||
ImGuiHelpers.ScaledDummy(3f);
|
||||
_uiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 2f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 2f);
|
||||
|
||||
if (_configService.Current.BroadcastEnabled)
|
||||
{
|
||||
@@ -287,7 +288,7 @@ namespace LightlessSync.UI
|
||||
|
||||
_uiSharedService.MediumText("Syncshell Finder", UIColors.Get("PairBlue"));
|
||||
|
||||
_uiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 2f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 2f);
|
||||
|
||||
ImGui.PushTextWrapPos();
|
||||
ImGui.Text("Allow your owned Syncshell to be indexed by the Nearby Syncshell Finder.");
|
||||
@@ -295,7 +296,7 @@ namespace LightlessSync.UI
|
||||
ImGui.PopTextWrapPos();
|
||||
|
||||
ImGuiHelpers.ScaledDummy(0.2f);
|
||||
_uiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 2f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 2f);
|
||||
|
||||
bool ShellFinderEnabled = _configService.Current.SyncshellFinderEnabled;
|
||||
bool isBroadcasting = _broadcastService.IsBroadcasting;
|
||||
|
||||
@@ -13,13 +13,15 @@ internal sealed partial class CharaDataHubUi
|
||||
AccessTypeDto.AllPairs => "All Pairs",
|
||||
AccessTypeDto.ClosePairs => "Direct Pairs",
|
||||
AccessTypeDto.Individuals => "Specified",
|
||||
AccessTypeDto.Public => "Everyone"
|
||||
AccessTypeDto.Public => "Everyone",
|
||||
_ => throw new NotSupportedException()
|
||||
};
|
||||
|
||||
private static string GetShareTypeString(ShareTypeDto dto) => dto switch
|
||||
{
|
||||
ShareTypeDto.Private => "Code Only",
|
||||
ShareTypeDto.Shared => "Shared"
|
||||
ShareTypeDto.Shared => "Shared",
|
||||
_ => throw new NotSupportedException()
|
||||
};
|
||||
|
||||
private static string GetWorldDataTooltipText(PoseEntryExtended poseEntry)
|
||||
@@ -31,7 +33,7 @@ internal sealed partial class CharaDataHubUi
|
||||
|
||||
private void GposeMetaInfoAction(Action<CharaDataMetaInfoExtendedDto?> gposeActionDraw, string actionDescription, CharaDataMetaInfoExtendedDto? dto, bool hasValidGposeTarget, bool isSpawning)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
StringBuilder sb = new();
|
||||
|
||||
sb.AppendLine(actionDescription);
|
||||
bool isDisabled = false;
|
||||
|
||||
@@ -406,7 +406,7 @@ internal sealed partial class CharaDataHubUi
|
||||
{
|
||||
_uiSharedService.BigText("Poses");
|
||||
var poseCount = updateDto.PoseList.Count();
|
||||
using (ImRaii.Disabled(poseCount >= maxPoses))
|
||||
using (ImRaii.Disabled(poseCount >= _maxPoses))
|
||||
{
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Plus, "Add new Pose"))
|
||||
{
|
||||
@@ -414,8 +414,8 @@ internal sealed partial class CharaDataHubUi
|
||||
}
|
||||
}
|
||||
ImGui.SameLine();
|
||||
using (ImRaii.PushColor(ImGuiCol.Text, UIColors.Get("LightlessYellow"), poseCount == maxPoses))
|
||||
ImGui.TextUnformatted($"{poseCount}/{maxPoses} poses attached");
|
||||
using (ImRaii.PushColor(ImGuiCol.Text, UIColors.Get("LightlessYellow"), poseCount == _maxPoses))
|
||||
ImGui.TextUnformatted($"{poseCount}/{_maxPoses} poses attached");
|
||||
ImGuiHelpers.ScaledDummy(5);
|
||||
|
||||
using var indent = ImRaii.PushIndent(10f);
|
||||
@@ -463,12 +463,16 @@ internal sealed partial class CharaDataHubUi
|
||||
else
|
||||
{
|
||||
var desc = pose.Description;
|
||||
if (ImGui.InputTextWithHint("##description", "Description", ref desc, 100))
|
||||
if (desc != null)
|
||||
{
|
||||
pose.Description = desc;
|
||||
updateDto.UpdatePoseList();
|
||||
if (ImGui.InputTextWithHint("##description", "Description", ref desc, 100))
|
||||
{
|
||||
pose.Description = desc;
|
||||
updateDto.UpdatePoseList();
|
||||
}
|
||||
ImGui.SameLine();
|
||||
}
|
||||
ImGui.SameLine();
|
||||
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Trash, "Delete"))
|
||||
{
|
||||
updateDto.RemovePose(pose);
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace LightlessSync.UI;
|
||||
|
||||
internal sealed partial class CharaDataHubUi : WindowMediatorSubscriberBase
|
||||
{
|
||||
private const int maxPoses = 10;
|
||||
private const int _maxPoses = 10;
|
||||
private readonly CharaDataManager _charaDataManager;
|
||||
private readonly CharaDataNearbyManager _charaDataNearbyManager;
|
||||
private readonly CharaDataConfigService _configService;
|
||||
@@ -33,7 +33,7 @@ internal sealed partial class CharaDataHubUi : WindowMediatorSubscriberBase
|
||||
private readonly UiSharedService _uiSharedService;
|
||||
private CancellationTokenSource _closalCts = new();
|
||||
private bool _disableUI = false;
|
||||
private CancellationTokenSource _disposalCts = new();
|
||||
private readonly CancellationTokenSource _disposalCts = new();
|
||||
private string _exportDescription = string.Empty;
|
||||
private string _filterCodeNote = string.Empty;
|
||||
private string _filterDescription = string.Empty;
|
||||
@@ -145,6 +145,8 @@ internal sealed partial class CharaDataHubUi : WindowMediatorSubscriberBase
|
||||
{
|
||||
_closalCts.CancelDispose();
|
||||
_disposalCts.CancelDispose();
|
||||
_disposalCts.Dispose();
|
||||
_closalCts.Dispose();
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
|
||||
@@ -27,6 +27,7 @@ using System.Collections.Immutable;
|
||||
using System.Globalization;
|
||||
using System.Numerics;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace LightlessSync.UI;
|
||||
|
||||
@@ -310,7 +311,7 @@ public class CompactUi : WindowMediatorSubscriberBase
|
||||
|
||||
private void DrawPairs()
|
||||
{
|
||||
var ySize = _transferPartHeight == 0
|
||||
float ySize = Math.Abs(_transferPartHeight) < 0.0001f
|
||||
? 1
|
||||
: (ImGui.GetWindowContentRegionMax().Y - ImGui.GetWindowContentRegionMin().Y
|
||||
+ ImGui.GetTextLineHeight() - ImGui.GetStyle().WindowPadding.Y - ImGui.GetStyle().WindowBorderSize) - _transferPartHeight - ImGui.GetCursorPosY();
|
||||
@@ -510,6 +511,7 @@ public class CompactUi : WindowMediatorSubscriberBase
|
||||
return new DownloadSummary(totalFiles, transferredFiles, transferredBytes, totalBytes);
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
private readonly record struct DownloadSummary(int TotalFiles, int TransferredFiles, long TransferredBytes, long TotalBytes)
|
||||
{
|
||||
public bool HasDownloads => TotalFiles > 0 || TotalBytes > 0;
|
||||
@@ -590,7 +592,7 @@ public class CompactUi : WindowMediatorSubscriberBase
|
||||
ImGui.PopStyleColor();
|
||||
|
||||
ImGuiHelpers.ScaledDummy(0.2f);
|
||||
_uiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 2f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 2f);
|
||||
|
||||
if (_configService.Current.BroadcastEnabled)
|
||||
{
|
||||
|
||||
@@ -119,6 +119,7 @@ public class DrawFolderGroup : DrawFolderBase
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.ArrowCircleLeft, "Leave Syncshell", menuWidth, true) && UiSharedService.CtrlPressed())
|
||||
{
|
||||
_ = _apiController.GroupLeave(_groupFullInfoDto);
|
||||
_lightlessMediator.Publish(new UserLeftSyncshell(_groupFullInfoDto.GID));
|
||||
ImGui.CloseCurrentPopup();
|
||||
}
|
||||
UiSharedService.AttachToolTip("Hold CTRL and click to leave this Syncshell" + (!string.Equals(_groupFullInfoDto.OwnerUID, _apiController.UID, StringComparison.Ordinal)
|
||||
|
||||
@@ -5,6 +5,7 @@ using LightlessSync.LightlessConfiguration.Models;
|
||||
using LightlessSync.PlayerData.Handlers;
|
||||
using LightlessSync.Services;
|
||||
using LightlessSync.Services.Mediator;
|
||||
using LightlessSync.Services.PairProcessing;
|
||||
using LightlessSync.WebAPI.Files;
|
||||
using LightlessSync.WebAPI.Files.Models;
|
||||
using Microsoft.Extensions.Logging;
|
||||
@@ -22,6 +23,7 @@ public class DownloadUi : WindowMediatorSubscriberBase
|
||||
private readonly UiSharedService _uiShared;
|
||||
private readonly PairProcessingLimiter _pairProcessingLimiter;
|
||||
private readonly ConcurrentDictionary<GameObjectHandler, bool> _uploadingPlayers = new();
|
||||
private readonly Dictionary<GameObjectHandler, Vector2> _smoothed = [];
|
||||
private bool _notificationDismissed = true;
|
||||
private int _lastDownloadStateHash = 0;
|
||||
|
||||
@@ -203,8 +205,18 @@ public class DownloadUi : WindowMediatorSubscriberBase
|
||||
|
||||
foreach (var transfer in _currentDownloads.ToList())
|
||||
{
|
||||
var screenPos = _dalamudUtilService.WorldToScreen(transfer.Key.GetGameObject());
|
||||
if (screenPos == Vector2.Zero) continue;
|
||||
var transferKey = transfer.Key;
|
||||
var rawPos = _dalamudUtilService.WorldToScreen(transferKey.GetGameObject());
|
||||
//If RawPos is zero, remove it from smoothed dictionary
|
||||
if (rawPos == Vector2.Zero)
|
||||
{
|
||||
_smoothed.Remove(transferKey);
|
||||
continue;
|
||||
}
|
||||
//Smoothing out the movement and fix jitter around the position.
|
||||
Vector2 screenPos = _smoothed.TryGetValue(transferKey, out var lastPos) ? (rawPos - lastPos).Length() < 4f ? lastPos : rawPos : rawPos;
|
||||
_smoothed[transferKey] = screenPos;
|
||||
|
||||
|
||||
var totalBytes = transfer.Value.Sum(c => c.Value.TotalBytes);
|
||||
var transferredBytes = transfer.Value.Sum(c => c.Value.TransferredBytes);
|
||||
|
||||
@@ -347,7 +347,7 @@ public sealed class DtrEntry : IDisposable, IHostedService
|
||||
try
|
||||
{
|
||||
var cid = _dalamudUtilService.GetCIDAsync().GetAwaiter().GetResult();
|
||||
var hashedCid = cid.ToString().GetHash256();
|
||||
var hashedCid = cid.ToString().GetBlake3Hash();
|
||||
_localHashedCid = hashedCid;
|
||||
_localHashedCidFetchedAt = now;
|
||||
return hashedCid;
|
||||
@@ -445,7 +445,7 @@ public sealed class DtrEntry : IDisposable, IHostedService
|
||||
return ($"{icon} OFF", colors, tooltip.ToString());
|
||||
}
|
||||
|
||||
private (string, Colors, string) FormatTooltip(string title, IEnumerable<string> names, string icon, Colors color)
|
||||
private static (string, Colors, string) FormatTooltip(string title, IEnumerable<string> names, string icon, Colors color)
|
||||
{
|
||||
var list = names.Where(x => !string.IsNullOrEmpty(x)).ToList();
|
||||
var tooltip = new StringBuilder()
|
||||
|
||||
@@ -9,6 +9,7 @@ using LightlessSync.API.Data;
|
||||
using LightlessSync.API.Dto.Group;
|
||||
using LightlessSync.Services;
|
||||
using LightlessSync.Services.Mediator;
|
||||
using LightlessSync.Services.Profiles;
|
||||
using LightlessSync.UI.Tags;
|
||||
using LightlessSync.Utils;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
@@ -25,6 +25,7 @@ using System.IO;
|
||||
using System.Numerics;
|
||||
using System.Threading.Tasks;
|
||||
using System.Linq;
|
||||
using LightlessSync.Services.Profiles;
|
||||
|
||||
namespace LightlessSync.UI;
|
||||
|
||||
@@ -91,14 +92,13 @@ public partial class EditProfileUi : WindowMediatorSubscriberBase
|
||||
private bool _wasOpen;
|
||||
|
||||
private Vector4 _currentBg = new(0.15f, 0.15f, 0.15f, 1f);
|
||||
private bool vanityInitialized; // useless for now
|
||||
private bool textEnabled;
|
||||
private bool glowEnabled;
|
||||
private Vector4 textColor;
|
||||
private Vector4 glowColor;
|
||||
|
||||
private record VanityState(bool TextEnabled, bool GlowEnabled, Vector4 TextColor, Vector4 GlowColor);
|
||||
private VanityState _savedVanity;
|
||||
private sealed record VanityState(bool TextEnabled, bool GlowEnabled, Vector4 TextColor, Vector4 GlowColor);
|
||||
private VanityState? _savedVanity;
|
||||
|
||||
public EditProfileUi(ILogger<EditProfileUi> logger, LightlessMediator mediator,
|
||||
ApiController apiController, UiSharedService uiSharedService, FileDialogManager fileDialogManager,
|
||||
@@ -161,7 +161,6 @@ public partial class EditProfileUi : WindowMediatorSubscriberBase
|
||||
glowColor = glowEnabled ? UIColors.HexToRgba(_apiController.TextGlowColorHex!) : Vector4.Zero;
|
||||
|
||||
_savedVanity = new VanityState(textEnabled, glowEnabled, textColor, glowColor);
|
||||
vanityInitialized = true;
|
||||
}
|
||||
|
||||
public override async void OnOpen()
|
||||
|
||||
@@ -177,13 +177,11 @@ public class IdDisplayHandler
|
||||
|
||||
Vector2 itemMin;
|
||||
Vector2 itemMax;
|
||||
Vector2 textSize;
|
||||
using (ImRaii.PushFont(font, textIsUid))
|
||||
{
|
||||
SeStringUtils.RenderSeStringWithHitbox(seString, rowStart, font, pair.UserData.UID);
|
||||
itemMin = ImGui.GetItemRectMin();
|
||||
itemMax = ImGui.GetItemRectMax();
|
||||
//textSize = itemMax - itemMin;
|
||||
}
|
||||
|
||||
if (useHighlight)
|
||||
@@ -227,7 +225,7 @@ public class IdDisplayHandler
|
||||
var nameRectMax = ImGui.GetItemRectMax();
|
||||
if (ImGui.IsItemHovered())
|
||||
{
|
||||
if (!string.Equals(_lastMouseOverUid, id))
|
||||
if (!string.Equals(_lastMouseOverUid, id, StringComparison.Ordinal))
|
||||
{
|
||||
_popupTime = DateTime.UtcNow.AddSeconds(_lightlessConfigService.Current.ProfileDelay);
|
||||
}
|
||||
@@ -248,7 +246,7 @@ public class IdDisplayHandler
|
||||
}
|
||||
else
|
||||
{
|
||||
if (string.Equals(_lastMouseOverUid, id))
|
||||
if (string.Equals(_lastMouseOverUid, id, StringComparison.Ordinal))
|
||||
{
|
||||
_mediator.Publish(new ProfilePopoutToggle(Pair: null));
|
||||
_lastMouseOverUid = string.Empty;
|
||||
|
||||
@@ -267,7 +267,7 @@ public partial class IntroUi : WindowMediatorSubscriberBase
|
||||
{
|
||||
UiSharedService.ColorTextWrapped("Your secret key must be exactly 64 characters long. Don't enter your Lodestone auth here.", ImGuiColors.DalamudRed);
|
||||
}
|
||||
else if (_secretKey.Length == 64 && !HexRegex().IsMatch(_secretKey))
|
||||
else if (_secretKey.Length == 64 && !SecretRegex().IsMatch(_secretKey))
|
||||
{
|
||||
UiSharedService.ColorTextWrapped("Your secret key can only contain ABCDEF and the numbers 0-9.", ImGuiColors.DalamudRed);
|
||||
}
|
||||
@@ -360,6 +360,6 @@ public partial class IntroUi : WindowMediatorSubscriberBase
|
||||
_tosParagraphs = [Strings.ToS.Paragraph1, Strings.ToS.Paragraph2, Strings.ToS.Paragraph3, Strings.ToS.Paragraph4, Strings.ToS.Paragraph5, Strings.ToS.Paragraph6];
|
||||
}
|
||||
|
||||
[GeneratedRegex("^([A-F0-9]{2})+")]
|
||||
private static partial Regex HexRegex();
|
||||
[GeneratedRegex("^[A-F0-9]{64}$", RegexOptions.Compiled | RegexOptions.CultureInvariant)]
|
||||
private static partial Regex SecretRegex();
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Dalamud.Interface.Colors;
|
||||
using Dalamud.Interface.Utility;
|
||||
using Dalamud.Interface.Utility.Raii;
|
||||
using LightlessSync.API.Data.Enum;
|
||||
@@ -174,6 +173,7 @@ internal class JoinSyncshellUI : WindowMediatorSubscriberBase
|
||||
joinPermissions.SetDisableAnimations(_ownPermissions.DisableGroupAnimations);
|
||||
joinPermissions.SetDisableVFX(_ownPermissions.DisableGroupVFX);
|
||||
_ = _apiController.GroupJoinFinalize(new GroupJoinDto(_groupJoinInfo.Group, _previousPassword, joinPermissions));
|
||||
Mediator.Publish(new UserJoinedSyncshell(_groupJoinInfo.Group.GID));
|
||||
IsOpen = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Colors;
|
||||
using Dalamud.Interface.Utility;
|
||||
using Dalamud.Interface.Utility.Raii;
|
||||
using Dalamud.Interface.Windowing;
|
||||
using LightlessSync.LightlessConfiguration;
|
||||
using LightlessSync.LightlessConfiguration.Models;
|
||||
using LightlessSync.Services;
|
||||
@@ -27,11 +25,11 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase
|
||||
private const float _titleMessageSpacing = 4f;
|
||||
private const float _actionButtonSpacing = 8f;
|
||||
|
||||
private readonly List<LightlessNotification> _notifications = new();
|
||||
private readonly List<LightlessNotification> _notifications = [];
|
||||
private readonly object _notificationLock = new();
|
||||
private readonly LightlessConfigService _configService;
|
||||
private readonly Dictionary<string, float> _notificationYOffsets = new();
|
||||
private readonly Dictionary<string, float> _notificationTargetYOffsets = new();
|
||||
private readonly Dictionary<string, float> _notificationYOffsets = [];
|
||||
private readonly Dictionary<string, float> _notificationTargetYOffsets = [];
|
||||
|
||||
public LightlessNotificationUi(ILogger<LightlessNotificationUi> logger, LightlessMediator mediator, PerformanceCollectorService performanceCollector, LightlessConfigService configService)
|
||||
: base(logger, mediator, "Lightless Notifications##LightlessNotifications", performanceCollector)
|
||||
@@ -45,7 +43,6 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase
|
||||
ImGuiWindowFlags.NoNav |
|
||||
ImGuiWindowFlags.NoBackground |
|
||||
ImGuiWindowFlags.NoCollapse |
|
||||
ImGuiWindowFlags.NoInputs |
|
||||
ImGuiWindowFlags.NoTitleBar |
|
||||
ImGuiWindowFlags.NoScrollbar |
|
||||
ImGuiWindowFlags.AlwaysAutoResize;
|
||||
@@ -68,7 +65,7 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase
|
||||
{
|
||||
lock (_notificationLock)
|
||||
{
|
||||
var existingNotification = _notifications.FirstOrDefault(n => n.Id == notification.Id);
|
||||
var existingNotification = _notifications.FirstOrDefault(n => string.Equals(n.Id, notification.Id, StringComparison.Ordinal));
|
||||
if (existingNotification != null)
|
||||
{
|
||||
UpdateExistingNotification(existingNotification, notification);
|
||||
@@ -103,7 +100,7 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase
|
||||
{
|
||||
lock (_notificationLock)
|
||||
{
|
||||
var notification = _notifications.FirstOrDefault(n => n.Id == id);
|
||||
var notification = _notifications.FirstOrDefault(n => string.Equals(n.Id, id, StringComparison.Ordinal));
|
||||
if (notification != null)
|
||||
{
|
||||
StartOutAnimation(notification);
|
||||
@@ -122,13 +119,13 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
}
|
||||
|
||||
private void StartOutAnimation(LightlessNotification notification)
|
||||
private static void StartOutAnimation(LightlessNotification notification)
|
||||
{
|
||||
notification.IsAnimatingOut = true;
|
||||
notification.IsAnimatingIn = false;
|
||||
}
|
||||
|
||||
private bool ShouldRemoveNotification(LightlessNotification notification) =>
|
||||
private static bool ShouldRemoveNotification(LightlessNotification notification) =>
|
||||
notification.IsAnimatingOut && notification.AnimationProgress <= 0.01f;
|
||||
|
||||
protected override void DrawInternal()
|
||||
@@ -185,7 +182,7 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase
|
||||
ImGui.SetCursorPosY(startY + yOffset);
|
||||
}
|
||||
|
||||
DrawNotification(notification, i);
|
||||
DrawNotification(notification);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -304,7 +301,7 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase
|
||||
return corner == NotificationCorner.Left ? new Vector2(-distance, 0) : new Vector2(distance, 0);
|
||||
}
|
||||
|
||||
private void DrawNotification(LightlessNotification notification, int index)
|
||||
private void DrawNotification(LightlessNotification notification)
|
||||
{
|
||||
var alpha = notification.AnimationProgress;
|
||||
if (alpha <= 0f) return;
|
||||
@@ -339,7 +336,7 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase
|
||||
var bgColor = CalculateBackgroundColor(alpha, ImGui.IsWindowHovered());
|
||||
var accentColor = GetNotificationAccentColor(notification.Type);
|
||||
accentColor.W *= alpha;
|
||||
|
||||
|
||||
DrawShadow(drawList, windowPos, windowSize, alpha);
|
||||
HandleClickToDismiss(notification);
|
||||
DrawBackground(drawList, windowPos, windowSize, bgColor);
|
||||
@@ -370,7 +367,7 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase
|
||||
return bgColor;
|
||||
}
|
||||
|
||||
private void DrawShadow(ImDrawListPtr drawList, Vector2 windowPos, Vector2 windowSize, float alpha)
|
||||
private static void DrawShadow(ImDrawListPtr drawList, Vector2 windowPos, Vector2 windowSize, float alpha)
|
||||
{
|
||||
var shadowOffset = new Vector2(1f, 1f);
|
||||
var shadowColor = new Vector4(0f, 0f, 0f, 0.4f * alpha);
|
||||
@@ -384,9 +381,13 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase
|
||||
|
||||
private void HandleClickToDismiss(LightlessNotification notification)
|
||||
{
|
||||
if (ImGui.IsWindowHovered() &&
|
||||
var pos = ImGui.GetWindowPos();
|
||||
var size = ImGui.GetWindowSize();
|
||||
bool hovered = ImGui.IsMouseHoveringRect(pos, new Vector2(pos.X + size.X, pos.Y + size.Y));
|
||||
|
||||
if ((hovered || ImGui.IsWindowHovered()) &&
|
||||
_configService.Current.DismissNotificationOnClick &&
|
||||
!notification.Actions.Any() &&
|
||||
notification.Actions.Count == 0 &&
|
||||
ImGui.IsMouseClicked(ImGuiMouseButton.Left))
|
||||
{
|
||||
notification.IsDismissed = true;
|
||||
@@ -394,7 +395,7 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawBackground(ImDrawListPtr drawList, Vector2 windowPos, Vector2 windowSize, Vector4 bgColor)
|
||||
private static void DrawBackground(ImDrawListPtr drawList, Vector2 windowPos, Vector2 windowSize, Vector4 bgColor)
|
||||
{
|
||||
drawList.AddRectFilled(
|
||||
windowPos,
|
||||
@@ -431,14 +432,14 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase
|
||||
);
|
||||
}
|
||||
|
||||
private void DrawDurationProgressBar(LightlessNotification notification, float alpha, Vector2 windowPos, Vector2 windowSize, ImDrawListPtr drawList)
|
||||
private static void DrawDurationProgressBar(LightlessNotification notification, float alpha, Vector2 windowPos, Vector2 windowSize, ImDrawListPtr drawList)
|
||||
{
|
||||
var progress = CalculateDurationProgress(notification);
|
||||
var progressBarColor = UIColors.Get("LightlessBlue");
|
||||
var progressHeight = 2f;
|
||||
var progressY = windowPos.Y + windowSize.Y - progressHeight;
|
||||
var progressWidth = windowSize.X * progress;
|
||||
|
||||
|
||||
DrawProgressBackground(drawList, windowPos, windowSize, progressY, progressHeight, progressBarColor, alpha);
|
||||
|
||||
if (progress > 0)
|
||||
@@ -447,7 +448,7 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawDownloadProgressBar(LightlessNotification notification, float alpha, Vector2 windowPos, Vector2 windowSize, ImDrawListPtr drawList)
|
||||
private static void DrawDownloadProgressBar(LightlessNotification notification, float alpha, Vector2 windowPos, Vector2 windowSize, ImDrawListPtr drawList)
|
||||
{
|
||||
var progress = Math.Clamp(notification.Progress, 0f, 1f);
|
||||
var progressBarColor = UIColors.Get("LightlessGreen");
|
||||
@@ -455,7 +456,7 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase
|
||||
// Position above the duration bar (2px duration bar + 1px spacing)
|
||||
var progressY = windowPos.Y + windowSize.Y - progressHeight - 3f;
|
||||
var progressWidth = windowSize.X * progress;
|
||||
|
||||
|
||||
DrawProgressBackground(drawList, windowPos, windowSize, progressY, progressHeight, progressBarColor, alpha);
|
||||
|
||||
if (progress > 0)
|
||||
@@ -464,14 +465,14 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
}
|
||||
|
||||
private float CalculateDurationProgress(LightlessNotification notification)
|
||||
private static float CalculateDurationProgress(LightlessNotification notification)
|
||||
{
|
||||
// Calculate duration timer progress
|
||||
var elapsed = DateTime.UtcNow - notification.CreatedAt;
|
||||
return Math.Min(1.0f, (float)(elapsed.TotalSeconds / notification.Duration.TotalSeconds));
|
||||
}
|
||||
|
||||
private void DrawProgressBackground(ImDrawListPtr drawList, Vector2 windowPos, Vector2 windowSize, float progressY, float progressHeight, Vector4 progressBarColor, float alpha)
|
||||
private static void DrawProgressBackground(ImDrawListPtr drawList, Vector2 windowPos, Vector2 windowSize, float progressY, float progressHeight, Vector4 progressBarColor, float alpha)
|
||||
{
|
||||
var bgProgressColor = new Vector4(progressBarColor.X * 0.3f, progressBarColor.Y * 0.3f, progressBarColor.Z * 0.3f, 0.5f * alpha);
|
||||
drawList.AddRectFilled(
|
||||
@@ -482,7 +483,7 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase
|
||||
);
|
||||
}
|
||||
|
||||
private void DrawProgressForeground(ImDrawListPtr drawList, Vector2 windowPos, float progressY, float progressHeight, float progressWidth, Vector4 progressBarColor, float alpha)
|
||||
private static void DrawProgressForeground(ImDrawListPtr drawList, Vector2 windowPos, float progressY, float progressHeight, float progressWidth, Vector4 progressBarColor, float alpha)
|
||||
{
|
||||
var progressColor = progressBarColor;
|
||||
progressColor.W *= alpha;
|
||||
@@ -512,13 +513,13 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
}
|
||||
|
||||
private float CalculateContentWidth(float windowWidth) =>
|
||||
private static float CalculateContentWidth(float windowWidth) =>
|
||||
windowWidth - (_contentPaddingX * 2);
|
||||
|
||||
private bool HasActions(LightlessNotification notification) =>
|
||||
private static bool HasActions(LightlessNotification notification) =>
|
||||
notification.Actions.Count > 0;
|
||||
|
||||
private void PositionActionsAtBottom(float windowHeight)
|
||||
private static void PositionActionsAtBottom(float windowHeight)
|
||||
{
|
||||
var actionHeight = ImGui.GetFrameHeight();
|
||||
var bottomY = windowHeight - _contentPaddingY - actionHeight;
|
||||
@@ -546,7 +547,7 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase
|
||||
return $"[{timestamp}] {notification.Title}";
|
||||
}
|
||||
|
||||
private float DrawWrappedText(string text, float wrapWidth)
|
||||
private static float DrawWrappedText(string text, float wrapWidth)
|
||||
{
|
||||
ImGui.PushTextWrapPos(ImGui.GetCursorPosX() + wrapWidth);
|
||||
var startY = ImGui.GetCursorPosY();
|
||||
@@ -556,7 +557,7 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase
|
||||
return height;
|
||||
}
|
||||
|
||||
private void DrawMessage(LightlessNotification notification, Vector2 contentPos, float contentWidth, float titleHeight, float alpha)
|
||||
private static void DrawMessage(LightlessNotification notification, Vector2 contentPos, float contentWidth, float titleHeight, float alpha)
|
||||
{
|
||||
if (string.IsNullOrEmpty(notification.Message)) return;
|
||||
|
||||
@@ -591,13 +592,13 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
}
|
||||
|
||||
private float CalculateActionButtonWidth(int actionCount, float availableWidth)
|
||||
private static float CalculateActionButtonWidth(int actionCount, float availableWidth)
|
||||
{
|
||||
var totalSpacing = (actionCount - 1) * _actionButtonSpacing;
|
||||
return (availableWidth - totalSpacing) / actionCount;
|
||||
}
|
||||
|
||||
private void PositionActionButton(int index, float startX, float buttonWidth)
|
||||
private static void PositionActionButton(int index, float startX, float buttonWidth)
|
||||
{
|
||||
var xPosition = startX + index * (buttonWidth + _actionButtonSpacing);
|
||||
ImGui.SetCursorPosX(xPosition);
|
||||
@@ -625,7 +626,7 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase
|
||||
|
||||
if (action.Icon != FontAwesomeIcon.None)
|
||||
{
|
||||
buttonPressed = DrawIconTextButton(action.Icon, action.Label, buttonWidth, alpha);
|
||||
buttonPressed = DrawIconTextButton(action.Icon, action.Label, buttonWidth);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -650,10 +651,10 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
}
|
||||
|
||||
private bool DrawIconTextButton(FontAwesomeIcon icon, string text, float width, float alpha)
|
||||
private static bool DrawIconTextButton(FontAwesomeIcon icon, string text, float width)
|
||||
{
|
||||
var drawList = ImGui.GetWindowDrawList();
|
||||
var cursorPos = ImGui.GetCursorScreenPos();
|
||||
ImGui.GetCursorScreenPos();
|
||||
var frameHeight = ImGui.GetFrameHeight();
|
||||
|
||||
Vector2 iconSize;
|
||||
@@ -729,7 +730,7 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase
|
||||
return ImGui.CalcTextSize(titleText, true, contentWidth).Y;
|
||||
}
|
||||
|
||||
private float CalculateMessageHeight(LightlessNotification notification, float contentWidth)
|
||||
private static float CalculateMessageHeight(LightlessNotification notification, float contentWidth)
|
||||
{
|
||||
if (string.IsNullOrEmpty(notification.Message)) return 0f;
|
||||
|
||||
@@ -737,7 +738,7 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase
|
||||
return 4f + messageHeight;
|
||||
}
|
||||
|
||||
private Vector4 GetNotificationAccentColor(NotificationType type)
|
||||
private static Vector4 GetNotificationAccentColor(NotificationType type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
namespace LightlessSync.UI.Models
|
||||
{
|
||||
public class ChangelogFile
|
||||
{
|
||||
public string Tagline { get; init; } = string.Empty;
|
||||
public string Subline { get; init; } = string.Empty;
|
||||
public List<ChangelogEntry> Changelog { get; init; } = new();
|
||||
public List<CreditCategory>? Credits { get; init; }
|
||||
}
|
||||
|
||||
public class ChangelogEntry
|
||||
{
|
||||
public string Name { get; init; } = string.Empty;
|
||||
public string Date { get; init; } = string.Empty;
|
||||
public string Tagline { get; init; } = string.Empty;
|
||||
public bool? IsCurrent { get; init; }
|
||||
public string? Message { get; init; }
|
||||
public List<ChangelogVersion>? Versions { get; init; }
|
||||
}
|
||||
|
||||
public class ChangelogVersion
|
||||
{
|
||||
public string Number { get; init; } = string.Empty;
|
||||
public List<string> Items { get; init; } = new();
|
||||
}
|
||||
|
||||
public class CreditCategory
|
||||
{
|
||||
public string Category { get; init; } = string.Empty;
|
||||
public List<CreditItem> Items { get; init; } = new();
|
||||
}
|
||||
|
||||
public class CreditItem
|
||||
{
|
||||
public string Name { get; init; } = string.Empty;
|
||||
public string Role { get; init; } = string.Empty;
|
||||
}
|
||||
|
||||
public class CreditsFile
|
||||
{
|
||||
public List<CreditCategory> Credits { get; init; } = new();
|
||||
}
|
||||
}
|
||||
12
LightlessSync/UI/Models/ChangelogEntry.cs
Normal file
12
LightlessSync/UI/Models/ChangelogEntry.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
namespace LightlessSync.UI.Models
|
||||
{
|
||||
public class ChangelogEntry
|
||||
{
|
||||
public string Name { get; init; } = string.Empty;
|
||||
public string Date { get; init; } = string.Empty;
|
||||
public string Tagline { get; init; } = string.Empty;
|
||||
public bool? IsCurrent { get; init; }
|
||||
public string? Message { get; init; }
|
||||
public List<ChangelogVersion>? Versions { get; init; }
|
||||
}
|
||||
}
|
||||
10
LightlessSync/UI/Models/ChangelogFile.cs
Normal file
10
LightlessSync/UI/Models/ChangelogFile.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace LightlessSync.UI.Models
|
||||
{
|
||||
public class ChangelogFile
|
||||
{
|
||||
public string Tagline { get; init; } = string.Empty;
|
||||
public string Subline { get; init; } = string.Empty;
|
||||
public List<ChangelogEntry> Changelog { get; init; } = new();
|
||||
public List<CreditCategory>? Credits { get; init; }
|
||||
}
|
||||
}
|
||||
8
LightlessSync/UI/Models/ChangelogVersion.cs
Normal file
8
LightlessSync/UI/Models/ChangelogVersion.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace LightlessSync.UI.Models
|
||||
{
|
||||
public class ChangelogVersion
|
||||
{
|
||||
public string Number { get; init; } = string.Empty;
|
||||
public List<string> Items { get; init; } = [];
|
||||
}
|
||||
}
|
||||
8
LightlessSync/UI/Models/CreditCategory.cs
Normal file
8
LightlessSync/UI/Models/CreditCategory.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace LightlessSync.UI.Models
|
||||
{
|
||||
public class CreditCategory
|
||||
{
|
||||
public string Category { get; init; } = string.Empty;
|
||||
public List<CreditItem> Items { get; init; } = [];
|
||||
}
|
||||
}
|
||||
8
LightlessSync/UI/Models/CreditItem.cs
Normal file
8
LightlessSync/UI/Models/CreditItem.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace LightlessSync.UI.Models
|
||||
{
|
||||
public class CreditItem
|
||||
{
|
||||
public string Name { get; init; } = string.Empty;
|
||||
public string Role { get; init; } = string.Empty;
|
||||
}
|
||||
}
|
||||
7
LightlessSync/UI/Models/CreditsFile.cs
Normal file
7
LightlessSync/UI/Models/CreditsFile.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace LightlessSync.UI.Models
|
||||
{
|
||||
public class CreditsFile
|
||||
{
|
||||
public List<CreditCategory> Credits { get; init; } = [];
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using Dalamud.Interface;
|
||||
using LightlessSync.LightlessConfiguration.Models;
|
||||
using System.Numerics;
|
||||
|
||||
namespace LightlessSync.UI.Models;
|
||||
|
||||
public class LightlessNotification
|
||||
{
|
||||
public string Id { get; set; } = Guid.NewGuid().ToString();
|
||||
@@ -20,13 +20,3 @@ public class LightlessNotification
|
||||
public bool IsAnimatingOut { get; set; } = false;
|
||||
public uint? SoundEffectId { get; set; } = null;
|
||||
}
|
||||
public class LightlessNotificationAction
|
||||
{
|
||||
public string Id { get; set; } = Guid.NewGuid().ToString();
|
||||
public string Label { get; set; } = string.Empty;
|
||||
public FontAwesomeIcon Icon { get; set; } = FontAwesomeIcon.None;
|
||||
public Vector4 Color { get; set; } = Vector4.One;
|
||||
public Action<LightlessNotification> OnClick { get; set; } = _ => { };
|
||||
public bool IsPrimary { get; set; } = false;
|
||||
public bool IsDestructive { get; set; } = false;
|
||||
}
|
||||
15
LightlessSync/UI/Models/LightlessNotificationAction.cs
Normal file
15
LightlessSync/UI/Models/LightlessNotificationAction.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using Dalamud.Interface;
|
||||
using System.Numerics;
|
||||
|
||||
namespace LightlessSync.UI.Models;
|
||||
|
||||
public class LightlessNotificationAction
|
||||
{
|
||||
public string Id { get; set; } = Guid.NewGuid().ToString();
|
||||
public string Label { get; set; } = string.Empty;
|
||||
public FontAwesomeIcon Icon { get; set; } = FontAwesomeIcon.None;
|
||||
public Vector4 Color { get; set; } = Vector4.One;
|
||||
public Action<LightlessNotification> OnClick { get; set; } = _ => { };
|
||||
public bool IsPrimary { get; set; } = false;
|
||||
public bool IsDestructive { get; set; } = false;
|
||||
}
|
||||
@@ -1,7 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using LightlessSync.API.Dto.Group;
|
||||
using LightlessSync.PlayerData.Factories;
|
||||
using LightlessSync.PlayerData.Pairs;
|
||||
|
||||
@@ -612,7 +612,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
}
|
||||
|
||||
private bool DrawStyleResetButton(string key, bool hasOverride, string? tooltipOverride = null)
|
||||
private static bool DrawStyleResetButton(string key, bool hasOverride, string? tooltipOverride = null)
|
||||
{
|
||||
using var id = ImRaii.PushId($"reset-{key}");
|
||||
using var disabled = ImRaii.Disabled(!hasOverride);
|
||||
@@ -736,7 +736,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
|
||||
_uiShared.DrawHelpText("Controls how many uploads can run at once.");
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 2f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 2f);
|
||||
|
||||
if (ImGui.Checkbox("Enable Pair Download Limiter", ref limitPairApplications))
|
||||
{
|
||||
@@ -783,7 +783,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
ImGui.TextColored(ImGuiColors.DalamudGrey, "Pair apply limiter is disabled.");
|
||||
}
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 2f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 2f);
|
||||
|
||||
if (ImGui.Checkbox("Use Alternative Upload Method", ref useAlternativeUpload))
|
||||
{
|
||||
@@ -899,13 +899,10 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
using var tree = ImRaii.TreeNode("Speed Test to Servers");
|
||||
if (tree)
|
||||
{
|
||||
if (_downloadServersTask == null || ((_downloadServersTask?.IsCompleted ?? false) &&
|
||||
(!_downloadServersTask?.IsCompletedSuccessfully ?? false)))
|
||||
if ((_downloadServersTask == null || ((_downloadServersTask?.IsCompleted ?? false) &&
|
||||
(!_downloadServersTask?.IsCompletedSuccessfully ?? false))) && _uiShared.IconTextButton(FontAwesomeIcon.GroupArrowsRotate, "Update Download Server List"))
|
||||
{
|
||||
if (_uiShared.IconTextButton(FontAwesomeIcon.GroupArrowsRotate, "Update Download Server List"))
|
||||
{
|
||||
_downloadServersTask = GetDownloadServerList();
|
||||
}
|
||||
_downloadServersTask = GetDownloadServerList();
|
||||
}
|
||||
|
||||
if (_downloadServersTask != null && _downloadServersTask.IsCompleted &&
|
||||
@@ -1136,9 +1133,9 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
.DeserializeAsync<List<string>>(await result.Content.ReadAsStreamAsync().ConfigureAwait(false))
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (Exception)
|
||||
{
|
||||
_logger.LogWarning(ex, "Failed to get download server list");
|
||||
_logger.LogWarning("Failed to get download server list");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
@@ -1219,7 +1216,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
UiSharedService.TooltipSeparator
|
||||
+ "Keeping LOD enabled can lead to more crashes. Use at your own risk.");
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessYellow"), 2f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessYellow"), 2f);
|
||||
}
|
||||
|
||||
private void DrawFileStorageSettings()
|
||||
@@ -1421,7 +1418,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
}
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessYellow"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessYellow"), 1.5f);
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
@@ -1453,7 +1450,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
_logger.LogWarning(ex, $"Could not delete file {file} because it is in use.");
|
||||
_logger.LogWarning(ex, "Could not delete file {file} because it is in use.", file);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1487,7 +1484,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
ImGui.EndDisabled();
|
||||
ImGui.Unindent();
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("DimRed"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("DimRed"), 1.5f);
|
||||
ImGui.TreePop();
|
||||
}
|
||||
}
|
||||
@@ -1500,8 +1497,6 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
|
||||
_lastTab = "General";
|
||||
//UiSharedService.FontText("Experimental", _uiShared.UidFont);
|
||||
//ImGui.Separator();
|
||||
|
||||
_uiShared.UnderlinedBigText("General Settings", UIColors.Get("LightlessBlue"));
|
||||
ImGui.Dummy(new Vector2(10));
|
||||
@@ -1539,7 +1534,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
ImGuiColors.DalamudRed);
|
||||
}
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
@@ -1567,7 +1562,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
_uiShared.DrawHelpText(
|
||||
"This will automatically populate user notes using the first encountered player name if the note was not set prior");
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
@@ -1635,7 +1630,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
|
||||
}
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
@@ -1675,7 +1670,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
_uiShared.DrawHelpText("When enabled, Lightfinder will automatically turn on after reconnecting to the Lightless server.");
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"), 1.5f);
|
||||
|
||||
ImGui.TextUnformatted("Lightfinder Nameplate Colors");
|
||||
if (ImGui.BeginTable("##LightfinderColorTable", 3, ImGuiTableFlags.Borders | ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit))
|
||||
@@ -1731,7 +1726,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
|
||||
ImGui.Spacing();
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"), 1.5f);
|
||||
|
||||
ImGui.TextUnformatted("Lightfinder Info Bar");
|
||||
if (ImGui.Checkbox("Show Lightfinder status in Server info bar", ref showLightfinderInDtr))
|
||||
@@ -1827,7 +1822,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
ImGui.EndDisabled();
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"), 1.5f);
|
||||
|
||||
ImGui.TextUnformatted("Alignment");
|
||||
ImGui.BeginDisabled(autoAlign);
|
||||
@@ -1952,7 +1947,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
|
||||
}
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"), 1.5f);
|
||||
|
||||
ImGui.TextUnformatted("Visibility");
|
||||
var showOwn = _configService.Current.LightfinderLabelShowOwn;
|
||||
@@ -1990,7 +1985,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
_uiShared.DrawHelpText("Toggles Lightfinder label when no nameplate(s) is visible.");
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"), 1.5f);
|
||||
|
||||
ImGui.TextUnformatted("Label");
|
||||
var useIcon = _configService.Current.LightfinderLabelUseIcon;
|
||||
@@ -2096,7 +2091,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
_lightfinderIconPresetIndex = -1;
|
||||
}
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
@@ -2184,7 +2179,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
|
||||
ImGui.Spacing();
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"), 1.5f);
|
||||
|
||||
ImGui.TextUnformatted("Server Info Bar Colors");
|
||||
|
||||
@@ -2236,7 +2231,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
|
||||
ImGui.Spacing();
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"), 1.5f);
|
||||
|
||||
ImGui.TextUnformatted("Nameplate Colors");
|
||||
|
||||
@@ -2281,7 +2276,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
|
||||
ImGui.Spacing();
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"), 1.5f);
|
||||
|
||||
ImGui.TextUnformatted("UI Theme");
|
||||
|
||||
@@ -2303,7 +2298,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
|
||||
DrawThemeOverridesSection();
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
@@ -2401,7 +2396,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
_configService.Save();
|
||||
}
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
@@ -2444,7 +2439,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
|
||||
_uiShared.DrawHelpText("Will show profiles that have the NSFW tag enabled");
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
ImGui.TreePop();
|
||||
}
|
||||
ImGui.Separator();
|
||||
@@ -2542,7 +2537,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
+ "Default: 165 thousand");
|
||||
}
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
@@ -2646,7 +2641,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
+ "Default: 250 thousand");
|
||||
}
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
@@ -2726,7 +2721,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
|
||||
ImGui.Dummy(new Vector2(5));
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("DimRed"), 3f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("DimRed"), 3f);
|
||||
var onlyUncompressed = textureConfig.OnlyDownscaleUncompressedTextures;
|
||||
if (ImGui.Checkbox("Only downscale uncompressed textures", ref onlyUncompressed))
|
||||
{
|
||||
@@ -2734,7 +2729,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
_playerPerformanceConfigService.Save();
|
||||
}
|
||||
_uiShared.DrawHelpText("If disabled, compressed textures will be targeted for downscaling too.");
|
||||
_uiShared.ColoredSeparator(UIColors.Get("DimRed"), 3f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("DimRed"), 3f);
|
||||
|
||||
ImGui.Dummy(new Vector2(5));
|
||||
|
||||
@@ -2742,7 +2737,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
|
||||
ImGui.Dummy(new Vector2(5));
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessYellow"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessYellow"), 1.5f);
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
@@ -2890,7 +2885,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
ImGui.EndPopup();
|
||||
}
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("DimRed"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("DimRed"), 1.5f);
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
@@ -3468,15 +3463,13 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
|
||||
private int _lastSelectedServerIndex = -1;
|
||||
private Task<(bool Success, bool PartialSuccess, string Result)>? _secretKeysConversionTask = null;
|
||||
private CancellationTokenSource _secretKeysConversionCts = new CancellationTokenSource();
|
||||
private CancellationTokenSource _secretKeysConversionCts = new();
|
||||
|
||||
private async Task<(bool Success, bool partialSuccess, string Result)> ConvertSecretKeysToUIDs(
|
||||
ServerStorage serverStorage, CancellationToken token)
|
||||
{
|
||||
List<Authentication> failedConversions = serverStorage.Authentications
|
||||
.Where(u => u.SecretKeyIdx == -1 && string.IsNullOrEmpty(u.UID)).ToList();
|
||||
List<Authentication> conversionsToAttempt = serverStorage.Authentications
|
||||
.Where(u => u.SecretKeyIdx != -1 && string.IsNullOrEmpty(u.UID)).ToList();
|
||||
List<Authentication> failedConversions = [.. serverStorage.Authentications.Where(u => u.SecretKeyIdx == -1 && string.IsNullOrEmpty(u.UID))];
|
||||
List<Authentication> conversionsToAttempt = [.. serverStorage.Authentications.Where(u => u.SecretKeyIdx != -1 && string.IsNullOrEmpty(u.UID))];
|
||||
List<Authentication> successfulConversions = [];
|
||||
Dictionary<string, List<Authentication>> secretKeyMapping = new(StringComparer.Ordinal);
|
||||
foreach (var authEntry in conversionsToAttempt)
|
||||
@@ -3546,6 +3539,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
sb.Append(string.Join(", ", failedConversions.Select(k => k.CharacterName)));
|
||||
}
|
||||
|
||||
_secretKeysConversionCts.Dispose();
|
||||
return (true, failedConversions.Count != 0, sb.ToString());
|
||||
}
|
||||
|
||||
@@ -3914,7 +3908,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
ImGui.Unindent();
|
||||
}
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
@@ -3956,7 +3950,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
|
||||
_uiShared.DrawHelpText("Click anywhere on a notification to dismiss it. Notifications with action buttons (like pair requests) are excluded.");
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
@@ -4119,7 +4113,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
ImGui.SetTooltip("Right click to reset to default (3).");
|
||||
_uiShared.DrawHelpText("Width of the colored accent bar on the left side.");
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
ImGui.TreePop();
|
||||
}
|
||||
}
|
||||
@@ -4214,7 +4208,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
if (ImGui.IsItemHovered())
|
||||
ImGui.SetTooltip("Right click to reset to default (20).");
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
@@ -4229,7 +4223,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
_uiShared.DrawHelpText(
|
||||
"Configure which sounds play for each notification type. Use the play button to preview sounds.");
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
@@ -4277,7 +4271,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
"Only show online notifications for pairs where you have set an individual note.");
|
||||
ImGui.Unindent();
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessGreen"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessGreen"), 1.5f);
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
@@ -4293,7 +4287,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
_uiShared.DrawHelpText(
|
||||
"When you receive a pair request, show Accept/Decline buttons in the notification.");
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
@@ -4309,7 +4303,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
_uiShared.DrawHelpText(
|
||||
"When a player exceeds performance thresholds or is auto-paused, show Pause/Unpause buttons in the notification.");
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessOrange"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessOrange"), 1.5f);
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
@@ -4324,7 +4318,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
|
||||
_uiShared.DrawHelpText("Disable warning notifications for missing optional plugins.");
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessYellow"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessYellow"), 1.5f);
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
@@ -4334,32 +4328,32 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
}
|
||||
|
||||
private NotificationLocation[] GetLightlessNotificationLocations()
|
||||
private static NotificationLocation[] GetLightlessNotificationLocations()
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
return
|
||||
[
|
||||
NotificationLocation.LightlessUi, NotificationLocation.Chat, NotificationLocation.ChatAndLightlessUi, NotificationLocation.Nowhere
|
||||
};
|
||||
];
|
||||
}
|
||||
|
||||
private NotificationLocation[] GetDownloadNotificationLocations()
|
||||
private static NotificationLocation[] GetDownloadNotificationLocations()
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
return
|
||||
[
|
||||
NotificationLocation.LightlessUi, NotificationLocation.TextOverlay, NotificationLocation.Nowhere
|
||||
};
|
||||
];
|
||||
}
|
||||
|
||||
private NotificationLocation[] GetClassicNotificationLocations()
|
||||
private static NotificationLocation[] GetClassicNotificationLocations()
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
return
|
||||
[
|
||||
NotificationLocation.Toast, NotificationLocation.Chat, NotificationLocation.Both,
|
||||
NotificationLocation.Nowhere
|
||||
};
|
||||
];
|
||||
}
|
||||
|
||||
private string GetNotificationLocationLabel(NotificationLocation location)
|
||||
private static string GetNotificationLocationLabel(NotificationLocation location)
|
||||
{
|
||||
return location switch
|
||||
{
|
||||
@@ -4374,7 +4368,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
};
|
||||
}
|
||||
|
||||
private string GetNotificationCornerLabel(NotificationCorner corner)
|
||||
private static string GetNotificationCornerLabel(NotificationCorner corner)
|
||||
{
|
||||
return corner switch
|
||||
{
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Colors;
|
||||
using Dalamud.Interface.ImGuiFileDialog;
|
||||
using Dalamud.Interface.Textures.TextureWraps;
|
||||
using Dalamud.Interface.Utility;
|
||||
using Dalamud.Interface.Utility.Raii;
|
||||
using LightlessSync.API.Data.Enum;
|
||||
using LightlessSync.API.Data.Extensions;
|
||||
using LightlessSync.API.Dto.Group;
|
||||
using LightlessSync.PlayerData.Pairs;
|
||||
using LightlessSync.Services;
|
||||
using LightlessSync.Services.Mediator;
|
||||
using LightlessSync.PlayerData.Pairs;
|
||||
using LightlessSync.WebAPI;
|
||||
using LightlessSync.Services.Profiles;
|
||||
using LightlessSync.UI.Services;
|
||||
using LightlessSync.WebAPI;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using SixLabors.ImageSharp;
|
||||
using System.Globalization;
|
||||
|
||||
namespace LightlessSync.UI;
|
||||
@@ -23,12 +25,12 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
||||
private readonly bool _isModerator = false;
|
||||
private readonly bool _isOwner = false;
|
||||
private readonly List<string> _oneTimeInvites = [];
|
||||
private readonly PairUiService _pairUiService;
|
||||
private readonly LightlessProfileManager _lightlessProfileManager;
|
||||
private readonly FileDialogManager _fileDialogManager;
|
||||
private readonly UiSharedService _uiSharedService;
|
||||
private readonly PairUiService _pairUiService;
|
||||
private List<BannedGroupUserDto> _bannedUsers = [];
|
||||
private LightlessGroupProfileData? _profileData = null;
|
||||
private IDalamudTextureWrap? _pfpTextureWrap;
|
||||
private string _profileDescription = string.Empty;
|
||||
private int _multiInvites;
|
||||
private string _newPassword;
|
||||
@@ -38,27 +40,34 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
||||
private int _pruneDays = 14;
|
||||
|
||||
public SyncshellAdminUI(ILogger<SyncshellAdminUI> logger, LightlessMediator mediator, ApiController apiController,
|
||||
UiSharedService uiSharedService, PairUiService pairUiService, GroupFullInfoDto groupFullInfo, PerformanceCollectorService performanceCollectorService, LightlessProfileManager lightlessProfileManager, FileDialogManager fileDialogManager)
|
||||
UiSharedService uiSharedService, PairUiService pairUiService, GroupFullInfoDto groupFullInfo, PerformanceCollectorService performanceCollectorService, LightlessProfileManager lightlessProfileManager)
|
||||
: base(logger, mediator, "Syncshell Admin Panel (" + groupFullInfo.GroupAliasOrGID + ")", performanceCollectorService)
|
||||
{
|
||||
GroupFullInfo = groupFullInfo;
|
||||
_apiController = apiController;
|
||||
_uiSharedService = uiSharedService;
|
||||
_pairUiService = pairUiService;
|
||||
_lightlessProfileManager = lightlessProfileManager;
|
||||
_fileDialogManager = fileDialogManager;
|
||||
|
||||
_pairUiService = pairUiService;
|
||||
_isOwner = string.Equals(GroupFullInfo.OwnerUID, _apiController.UID, StringComparison.Ordinal);
|
||||
_isModerator = GroupFullInfo.GroupUserInfo.IsModerator();
|
||||
_newPassword = string.Empty;
|
||||
_multiInvites = 30;
|
||||
_pwChangeSuccess = true;
|
||||
IsOpen = true;
|
||||
Mediator.Subscribe<ClearProfileGroupDataMessage>(this, (msg) =>
|
||||
{
|
||||
if (msg.GroupData == null || string.Equals(msg.GroupData.AliasOrGID, GroupFullInfo.Group.AliasOrGID, StringComparison.Ordinal))
|
||||
{
|
||||
_pfpTextureWrap?.Dispose();
|
||||
_pfpTextureWrap = null;
|
||||
}
|
||||
});
|
||||
SizeConstraints = new WindowSizeConstraints()
|
||||
{
|
||||
MinimumSize = new(700, 500),
|
||||
MaximumSize = new(700, 2000),
|
||||
};
|
||||
_pairUiService = pairUiService;
|
||||
}
|
||||
|
||||
public GroupFullInfoDto GroupFullInfo { get; private set; }
|
||||
@@ -84,7 +93,7 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
||||
var perm = GroupFullInfo.GroupPermissions;
|
||||
|
||||
using var tabbar = ImRaii.TabBar("syncshell_tab_" + GroupFullInfo.GID);
|
||||
|
||||
|
||||
if (tabbar)
|
||||
{
|
||||
DrawInvites(perm);
|
||||
@@ -92,7 +101,7 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
||||
DrawManagement();
|
||||
|
||||
DrawPermission(perm);
|
||||
|
||||
|
||||
DrawProfile();
|
||||
}
|
||||
}
|
||||
@@ -193,6 +202,7 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
||||
ownerTab.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawProfile()
|
||||
{
|
||||
var profileTab = ImRaii.TabItem("Profile");
|
||||
@@ -220,7 +230,7 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
||||
ImGui.BulletText(_profileData.IsDisabled ? "Profile disabled for viewers" : "Profile active");
|
||||
|
||||
ImGuiHelpers.ScaledDummy(2f);
|
||||
_uiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
ImGuiHelpers.ScaledDummy(2f);
|
||||
|
||||
UiSharedService.TextWrapped("Open the syncshell profile editor to update images, description, tags, and visibility settings.");
|
||||
@@ -395,7 +405,7 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
||||
}
|
||||
}
|
||||
}
|
||||
_uiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
ImGui.TreePop();
|
||||
}
|
||||
ImGui.Separator();
|
||||
@@ -486,7 +496,7 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
||||
UiSharedService.TextWrapped($"Syncshell was pruned and {_pruneTask.Result} inactive user(s) have been removed.");
|
||||
}
|
||||
}
|
||||
_uiSharedService.ColoredSeparator(UIColors.Get("DimRed"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("DimRed"), 1.5f);
|
||||
ImGui.TreePop();
|
||||
}
|
||||
ImGui.Separator();
|
||||
@@ -532,7 +542,7 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
||||
}
|
||||
ImGui.EndTable();
|
||||
}
|
||||
_uiSharedService.ColoredSeparator(UIColors.Get("LightlessYellow"), 1.5f);
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessYellow"), 1.5f);
|
||||
ImGui.TreePop();
|
||||
}
|
||||
ImGui.Separator();
|
||||
@@ -584,8 +594,10 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
||||
}
|
||||
inviteTab.Dispose();
|
||||
}
|
||||
|
||||
public override void OnClose()
|
||||
{
|
||||
Mediator.Publish(new RemoveWindowMessage(this));
|
||||
_pfpTextureWrap?.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ using Dalamud.Interface;
|
||||
using Dalamud.Interface.Colors;
|
||||
using Dalamud.Interface.Utility;
|
||||
using Dalamud.Interface.Utility.Raii;
|
||||
using LightlessSync.API.Data;
|
||||
using LightlessSync.API.Data.Enum;
|
||||
using LightlessSync.API.Data.Extensions;
|
||||
using LightlessSync.API.Dto;
|
||||
@@ -29,11 +30,15 @@ public class SyncshellFinderUI : WindowMediatorSubscriberBase
|
||||
private readonly List<GroupJoinDto> _nearbySyncshells = [];
|
||||
private List<GroupFullInfoDto> _currentSyncshells = [];
|
||||
private int _selectedNearbyIndex = -1;
|
||||
private int _syncshellPageIndex = 0;
|
||||
private readonly HashSet<string> _recentlyJoined = new(StringComparer.Ordinal);
|
||||
|
||||
private GroupJoinDto? _joinDto;
|
||||
private GroupJoinInfoDto? _joinInfo;
|
||||
private DefaultPermissionsDto _ownPermissions = null!;
|
||||
private const bool _useTestSyncshells = false;
|
||||
|
||||
private bool _compactView = false;
|
||||
|
||||
public SyncshellFinderUI(
|
||||
ILogger<SyncshellFinderUI> logger,
|
||||
@@ -62,6 +67,8 @@ public class SyncshellFinderUI : WindowMediatorSubscriberBase
|
||||
|
||||
Mediator.Subscribe<SyncshellBroadcastsUpdatedMessage>(this, async _ => await RefreshSyncshellsAsync().ConfigureAwait(false));
|
||||
Mediator.Subscribe<BroadcastStatusChangedMessage>(this, async _ => await RefreshSyncshellsAsync().ConfigureAwait(false));
|
||||
Mediator.Subscribe<UserLeftSyncshell>(this, async _ => await RefreshSyncshellsAsync(_.gid).ConfigureAwait(false));
|
||||
Mediator.Subscribe<UserJoinedSyncshell>(this, async _ => await RefreshSyncshellsAsync(_.gid).ConfigureAwait(false));
|
||||
}
|
||||
|
||||
public override async void OnOpen()
|
||||
@@ -72,9 +79,21 @@ public class SyncshellFinderUI : WindowMediatorSubscriberBase
|
||||
|
||||
protected override void DrawInternal()
|
||||
{
|
||||
_uiSharedService.MediumText("Nearby Syncshells", UIColors.Get("PairBlue"));
|
||||
_uiSharedService.ColoredSeparator(UIColors.Get("PairBlue"));
|
||||
ImGui.BeginGroup();
|
||||
_uiSharedService.MediumText("Nearby Syncshells", UIColors.Get("LightlessPurple"));
|
||||
ImGui.SameLine();
|
||||
|
||||
string checkboxLabel = "Compact view";
|
||||
float availWidth = ImGui.GetContentRegionAvail().X;
|
||||
float checkboxWidth = ImGui.CalcTextSize(checkboxLabel).X + ImGui.GetFrameHeight();
|
||||
|
||||
float rightX = ImGui.GetCursorPosX() + availWidth - checkboxWidth - 4.0f;
|
||||
ImGui.SetCursorPosX(rightX);
|
||||
ImGui.Checkbox(checkboxLabel, ref _compactView);
|
||||
ImGui.EndGroup();
|
||||
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"));
|
||||
ImGui.Dummy(new Vector2(0, 2 * ImGuiHelpers.GlobalScale));
|
||||
if (_nearbySyncshells.Count == 0)
|
||||
{
|
||||
ImGui.TextColored(ImGuiColors.DalamudGrey, "No nearby syncshells are being broadcasted.");
|
||||
@@ -82,13 +101,13 @@ public class SyncshellFinderUI : WindowMediatorSubscriberBase
|
||||
if (!_broadcastService.IsBroadcasting)
|
||||
{
|
||||
|
||||
_uiSharedService.ColoredSeparator(UIColors.Get("LightlessYellow"));
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessYellow"));
|
||||
|
||||
ImGui.TextColored(UIColors.Get("LightlessYellow"), "Lightfinder is currently disabled, to locate nearby syncshells, Lightfinder must be active.");
|
||||
ImGuiHelpers.ScaledDummy(0.5f);
|
||||
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.FrameRounding, 10.0f);
|
||||
ImGui.PushStyleColor(ImGuiCol.Button, UIColors.Get("PairBlue"));
|
||||
ImGui.PushStyleColor(ImGuiCol.Button, UIColors.Get("LightlessPurple"));
|
||||
|
||||
if (ImGui.Button("Open Lightfinder", new Vector2(200 * ImGuiHelpers.GlobalScale, 0)))
|
||||
{
|
||||
@@ -104,106 +123,295 @@ public class SyncshellFinderUI : WindowMediatorSubscriberBase
|
||||
return;
|
||||
}
|
||||
|
||||
DrawSyncshellTable();
|
||||
var cardData = new List<(GroupJoinDto Shell, string BroadcasterName)>();
|
||||
var broadcasts = _broadcastScannerService.GetActiveSyncshellBroadcasts();
|
||||
|
||||
foreach (var shell in _nearbySyncshells)
|
||||
{
|
||||
string broadcasterName;
|
||||
|
||||
if (_useTestSyncshells)
|
||||
{
|
||||
var displayName = !string.IsNullOrEmpty(shell.Group.Alias)
|
||||
? shell.Group.Alias
|
||||
: shell.Group.GID;
|
||||
|
||||
broadcasterName = $"Tester of {displayName}";
|
||||
}
|
||||
else
|
||||
{
|
||||
var broadcast = broadcasts
|
||||
.FirstOrDefault(b => string.Equals(b.GID, shell.Group.GID, StringComparison.Ordinal));
|
||||
|
||||
if (broadcast == null)
|
||||
continue;
|
||||
|
||||
var (name, address) = _dalamudUtilService.FindPlayerByNameHash(broadcast.HashedCID);
|
||||
if (string.IsNullOrEmpty(name))
|
||||
continue;
|
||||
|
||||
var worldName = _dalamudUtilService.GetWorldNameFromPlayerAddress(address);
|
||||
broadcasterName = !string.IsNullOrEmpty(worldName)
|
||||
? $"{name} ({worldName})"
|
||||
: name;
|
||||
}
|
||||
|
||||
cardData.Add((shell, broadcasterName));
|
||||
}
|
||||
|
||||
if (cardData.Count == 0)
|
||||
{
|
||||
ImGui.TextColored(ImGuiColors.DalamudGrey, "No nearby syncshells are being broadcasted.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_compactView)
|
||||
{
|
||||
DrawSyncshellGrid(cardData);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawSyncshellList(cardData);
|
||||
}
|
||||
|
||||
|
||||
if (_joinDto != null && _joinInfo != null && _joinInfo.Success)
|
||||
DrawConfirmation();
|
||||
}
|
||||
|
||||
private void DrawSyncshellTable()
|
||||
private void DrawSyncshellList(List<(GroupJoinDto Shell, string BroadcasterName)> listData)
|
||||
{
|
||||
if (ImGui.BeginTable("##NearbySyncshellsTable", 3, ImGuiTableFlags.Borders | ImGuiTableFlags.RowBg))
|
||||
const int shellsPerPage = 3;
|
||||
var totalPages = (int)Math.Ceiling(listData.Count / (float)shellsPerPage);
|
||||
if (totalPages <= 0)
|
||||
totalPages = 1;
|
||||
|
||||
_syncshellPageIndex = Math.Clamp(_syncshellPageIndex, 0, totalPages - 1);
|
||||
|
||||
var firstIndex = _syncshellPageIndex * shellsPerPage;
|
||||
var lastExclusive = Math.Min(firstIndex + shellsPerPage, listData.Count);
|
||||
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.FrameRounding, 8.0f);
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.FrameBorderSize, 1.0f);
|
||||
|
||||
for (int index = firstIndex; index < lastExclusive; index++)
|
||||
{
|
||||
ImGui.TableSetupColumn("Syncshell", ImGuiTableColumnFlags.WidthStretch);
|
||||
ImGui.TableSetupColumn("Broadcaster", ImGuiTableColumnFlags.WidthStretch);
|
||||
ImGui.TableSetupColumn("Join", ImGuiTableColumnFlags.WidthFixed, 80f * ImGuiHelpers.GlobalScale);
|
||||
ImGui.TableHeadersRow();
|
||||
var (shell, broadcasterName) = listData[index];
|
||||
|
||||
foreach (var shell in _nearbySyncshells)
|
||||
{
|
||||
// Check if there is an active broadcast for this syncshell, if not, skipping this syncshell
|
||||
var broadcast = _broadcastScannerService.GetActiveSyncshellBroadcasts()
|
||||
.FirstOrDefault(b => string.Equals(b.GID, shell.Group.GID, StringComparison.Ordinal));
|
||||
ImGui.PushID(shell.Group.GID);
|
||||
float rowHeight = 90f * ImGuiHelpers.GlobalScale;
|
||||
|
||||
if (broadcast == null)
|
||||
continue; // no active broadcasts
|
||||
ImGui.BeginChild($"ShellRow##{shell.Group.GID}", new Vector2(-1, rowHeight), border: true);
|
||||
|
||||
var (Name, Address) = _dalamudUtilService.FindPlayerByNameHash(broadcast.HashedCID);
|
||||
if (string.IsNullOrEmpty(Name))
|
||||
continue; // broadcaster not found in area, skipping
|
||||
var displayName = !string.IsNullOrEmpty(shell.Group.Alias) ? shell.Group.Alias : shell.Group.GID;
|
||||
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableNextColumn();
|
||||
var style = ImGui.GetStyle();
|
||||
float startX = ImGui.GetCursorPosX();
|
||||
float regionW = ImGui.GetContentRegionAvail().X;
|
||||
float rightTxtW = ImGui.CalcTextSize(broadcasterName).X;
|
||||
|
||||
var displayName = !string.IsNullOrEmpty(shell.Group.Alias) ? shell.Group.Alias : shell.Group.GID;
|
||||
ImGui.TextUnformatted(displayName);
|
||||
_uiSharedService.MediumText(displayName, UIColors.Get("LightlessPurple"));
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
var worldName = _dalamudUtilService.GetWorldNameFromPlayerAddress(Address);
|
||||
var broadcasterName = !string.IsNullOrEmpty(worldName) ? $"{Name} ({worldName})" : Name;
|
||||
ImGui.TextUnformatted(broadcasterName);
|
||||
float rightX = startX + regionW - rightTxtW - style.ItemSpacing.X;
|
||||
ImGui.SameLine();
|
||||
ImGui.SetCursorPosX(rightX);
|
||||
ImGui.TextUnformatted(broadcasterName);
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"));
|
||||
|
||||
var label = $"Join##{shell.Group.GID}";
|
||||
ImGui.PushStyleColor(ImGuiCol.Button, UIColors.Get("LightlessGreen"));
|
||||
ImGui.PushStyleColor(ImGuiCol.ButtonHovered, UIColors.Get("LightlessGreen").WithAlpha(0.85f));
|
||||
ImGui.PushStyleColor(ImGuiCol.ButtonActive, UIColors.Get("LightlessGreen").WithAlpha(0.75f));
|
||||
ImGui.Dummy(new Vector2(0, 6 * ImGuiHelpers.GlobalScale));
|
||||
|
||||
var isAlreadyMember = _currentSyncshells.Exists(g => string.Equals(g.GID, shell.GID, StringComparison.Ordinal));
|
||||
var isRecentlyJoined = _recentlyJoined.Contains(shell.GID);
|
||||
|
||||
if (!isAlreadyMember && !isRecentlyJoined)
|
||||
{
|
||||
if (ImGui.Button(label))
|
||||
{
|
||||
_logger.LogInformation($"Join requested for Syncshell {shell.Group.GID} ({shell.Group.Alias})");
|
||||
DrawJoinButton(shell);
|
||||
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var info = await _apiController.GroupJoinHashed(new GroupJoinHashedDto(
|
||||
shell.Group,
|
||||
shell.Password,
|
||||
shell.GroupUserPreferredPermissions
|
||||
)).ConfigureAwait(false);
|
||||
ImGui.EndChild();
|
||||
ImGui.PopID();
|
||||
|
||||
if (info != null && info.Success)
|
||||
{
|
||||
_joinDto = new GroupJoinDto(shell.Group, shell.Password, shell.GroupUserPreferredPermissions);
|
||||
_joinInfo = info;
|
||||
_ownPermissions = _apiController.DefaultPermissions.DeepClone()!;
|
||||
ImGui.Dummy(new Vector2(0, 2 * ImGuiHelpers.GlobalScale));
|
||||
}
|
||||
|
||||
_logger.LogInformation($"Fetched join info for {shell.Group.GID}");
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogWarning($"Failed to join {shell.Group.GID}: info was null or unsuccessful");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, $"Join failed for {shell.Group.GID}");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
using (ImRaii.Disabled())
|
||||
{
|
||||
ImGui.Button(label);
|
||||
}
|
||||
UiSharedService.AttachToolTip("Already a member or owner of this Syncshell.");
|
||||
}
|
||||
ImGui.PopStyleColor(3);
|
||||
}
|
||||
ImGui.PopStyleVar(2);
|
||||
|
||||
ImGui.EndTable();
|
||||
DrawPagination(totalPages);
|
||||
}
|
||||
|
||||
private void DrawSyncshellGrid(List<(GroupJoinDto Shell, string BroadcasterName)> cardData)
|
||||
{
|
||||
const int shellsPerPage = 4;
|
||||
var totalPages = (int)Math.Ceiling(cardData.Count / (float)shellsPerPage);
|
||||
if (totalPages <= 0)
|
||||
totalPages = 1;
|
||||
|
||||
_syncshellPageIndex = Math.Clamp(_syncshellPageIndex, 0, totalPages - 1);
|
||||
|
||||
var firstIndex = _syncshellPageIndex * shellsPerPage;
|
||||
var lastExclusive = Math.Min(firstIndex + shellsPerPage, cardData.Count);
|
||||
|
||||
var avail = ImGui.GetContentRegionAvail();
|
||||
var spacing = ImGui.GetStyle().ItemSpacing;
|
||||
|
||||
var cardWidth = (avail.X - spacing.X) / 2.0f;
|
||||
var cardHeight = (avail.Y - spacing.Y - (ImGui.GetFrameHeightWithSpacing() * 2.0f)) / 2.0f;
|
||||
cardHeight = MathF.Max(110f * ImGuiHelpers.GlobalScale, cardHeight);
|
||||
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.FrameRounding, 8.0f);
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.FrameBorderSize, 1.0f);
|
||||
|
||||
for (int index = firstIndex; index < lastExclusive; index++)
|
||||
{
|
||||
var localIndex = index - firstIndex;
|
||||
var (shell, broadcasterName) = cardData[index];
|
||||
|
||||
if (localIndex % 2 != 0)
|
||||
ImGui.SameLine();
|
||||
|
||||
ImGui.PushID(shell.Group.GID);
|
||||
|
||||
ImGui.BeginGroup();
|
||||
_ = ImGui.BeginChild("ShellCard##" + shell.Group.GID, new Vector2(cardWidth, cardHeight), border: true);
|
||||
|
||||
var displayName = !string.IsNullOrEmpty(shell.Group.Alias)
|
||||
? shell.Group.Alias
|
||||
: shell.Group.GID;
|
||||
|
||||
_uiSharedService.MediumText(displayName, UIColors.Get("LightlessPurple"));
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"));
|
||||
|
||||
ImGui.TextColored(ImGuiColors.DalamudGrey, "Broadcaster");
|
||||
ImGui.TextUnformatted(broadcasterName);
|
||||
|
||||
ImGui.Dummy(new Vector2(0, 6 * ImGuiHelpers.GlobalScale));
|
||||
|
||||
var buttonHeight = ImGui.GetFrameHeightWithSpacing();
|
||||
var remainingY = ImGui.GetContentRegionAvail().Y - buttonHeight;
|
||||
if (remainingY > 0)
|
||||
ImGui.Dummy(new Vector2(0, remainingY));
|
||||
|
||||
DrawJoinButton(shell);
|
||||
|
||||
ImGui.EndChild();
|
||||
ImGui.EndGroup();
|
||||
|
||||
ImGui.PopID();
|
||||
}
|
||||
|
||||
ImGui.Dummy(new Vector2(0, 2 * ImGuiHelpers.GlobalScale));
|
||||
ImGui.PopStyleVar(2);
|
||||
|
||||
DrawPagination(totalPages);
|
||||
}
|
||||
|
||||
private void DrawPagination(int totalPages)
|
||||
{
|
||||
if (totalPages > 1)
|
||||
{
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("PairBlue"));
|
||||
|
||||
var style = ImGui.GetStyle();
|
||||
string pageLabel = $"Page {_syncshellPageIndex + 1}/{totalPages}";
|
||||
|
||||
float prevWidth = ImGui.CalcTextSize("<").X + style.FramePadding.X * 2;
|
||||
float nextWidth = ImGui.CalcTextSize(">").X + style.FramePadding.X * 2;
|
||||
float textWidth = ImGui.CalcTextSize(pageLabel).X;
|
||||
|
||||
float totalWidth = prevWidth + textWidth + nextWidth + style.ItemSpacing.X * 2;
|
||||
|
||||
float availWidth = ImGui.GetContentRegionAvail().X;
|
||||
float offsetX = (availWidth - totalWidth) * 0.5f;
|
||||
|
||||
ImGui.SetCursorPosX(ImGui.GetCursorPosX() + offsetX);
|
||||
|
||||
if (ImGui.Button("<##PrevSyncshellPage") && _syncshellPageIndex > 0)
|
||||
_syncshellPageIndex--;
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGui.Text(pageLabel);
|
||||
|
||||
ImGui.SameLine();
|
||||
if (ImGui.Button(">##NextSyncshellPage") && _syncshellPageIndex < totalPages - 1)
|
||||
_syncshellPageIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawJoinButton(dynamic shell)
|
||||
{
|
||||
const string visibleLabel = "Join";
|
||||
var label = $"{visibleLabel}##{shell.Group.GID}";
|
||||
|
||||
ImGui.PushStyleColor(ImGuiCol.Button, UIColors.Get("LightlessGreen"));
|
||||
ImGui.PushStyleColor(ImGuiCol.ButtonHovered, UIColors.Get("LightlessGreen").WithAlpha(0.85f));
|
||||
ImGui.PushStyleColor(ImGuiCol.ButtonActive, UIColors.Get("LightlessGreen").WithAlpha(0.75f));
|
||||
|
||||
var isAlreadyMember = _currentSyncshells.Exists(g => string.Equals(g.GID, shell.GID, StringComparison.Ordinal));
|
||||
var isRecentlyJoined = _recentlyJoined.Contains(shell.GID);
|
||||
|
||||
Vector2 buttonSize;
|
||||
|
||||
if (!_compactView)
|
||||
{
|
||||
var style = ImGui.GetStyle();
|
||||
var textSize = ImGui.CalcTextSize(visibleLabel);
|
||||
|
||||
var width = textSize.X + style.FramePadding.X * 20f;
|
||||
buttonSize = new Vector2(width, 0);
|
||||
|
||||
float availX = ImGui.GetContentRegionAvail().X;
|
||||
float curX = ImGui.GetCursorPosX();
|
||||
float newX = curX + (availX - buttonSize.X);
|
||||
ImGui.SetCursorPosX(newX);
|
||||
}
|
||||
else
|
||||
{
|
||||
buttonSize = new Vector2(-1, 0);
|
||||
}
|
||||
|
||||
if (!isAlreadyMember && !isRecentlyJoined)
|
||||
{
|
||||
if (ImGui.Button(label, buttonSize))
|
||||
{
|
||||
_logger.LogInformation($"Join requested for Syncshell {shell.Group.GID} ({shell.Group.Alias})");
|
||||
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var info = await _apiController.GroupJoinHashed(new GroupJoinHashedDto(
|
||||
shell.Group,
|
||||
shell.Password,
|
||||
shell.GroupUserPreferredPermissions
|
||||
)).ConfigureAwait(false);
|
||||
|
||||
if (info != null && info.Success)
|
||||
{
|
||||
_joinDto = new GroupJoinDto(shell.Group, shell.Password, shell.GroupUserPreferredPermissions);
|
||||
_joinInfo = info;
|
||||
_ownPermissions = _apiController.DefaultPermissions.DeepClone()!;
|
||||
|
||||
_logger.LogInformation($"Fetched join info for {shell.Group.GID}");
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogWarning($"Failed to join {shell.Group.GID}: info was null or unsuccessful");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, $"Join failed for {shell.Group.GID}");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
using (ImRaii.Disabled())
|
||||
{
|
||||
ImGui.Button(label, buttonSize);
|
||||
}
|
||||
|
||||
UiSharedService.AttachToolTip("Already a member or owner of this Syncshell.");
|
||||
}
|
||||
|
||||
ImGui.PopStyleColor(3);
|
||||
}
|
||||
private void DrawConfirmation()
|
||||
{
|
||||
if (_joinDto != null && _joinInfo != null)
|
||||
@@ -263,53 +471,97 @@ public class SyncshellFinderUI : WindowMediatorSubscriberBase
|
||||
ImGui.NewLine();
|
||||
}
|
||||
|
||||
private async Task RefreshSyncshellsAsync()
|
||||
private async Task RefreshSyncshellsAsync(string? gid = null)
|
||||
{
|
||||
var syncshellBroadcasts = _broadcastScannerService.GetActiveSyncshellBroadcasts();
|
||||
var snapshot = _pairUiService.GetSnapshot();
|
||||
_currentSyncshells = snapshot.GroupPairs.Keys.ToList();
|
||||
|
||||
_recentlyJoined.RemoveWhere(gid => _currentSyncshells.Any(s => string.Equals(s.GID, gid, StringComparison.Ordinal)));
|
||||
_currentSyncshells = [.. snapshot.GroupPairs.Keys];
|
||||
|
||||
if (syncshellBroadcasts.Count == 0)
|
||||
_recentlyJoined.RemoveWhere(gid =>
|
||||
_currentSyncshells.Exists(s => string.Equals(s.GID, gid, StringComparison.Ordinal)));
|
||||
|
||||
List<GroupJoinDto>? updatedList = [];
|
||||
|
||||
if (_useTestSyncshells)
|
||||
{
|
||||
updatedList = BuildTestSyncshells();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (syncshellBroadcasts.Count == 0)
|
||||
{
|
||||
ClearSyncshells();
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var groups = await _apiController.GetBroadcastedGroups(syncshellBroadcasts)
|
||||
.ConfigureAwait(false);
|
||||
updatedList = groups?.ToList();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to refresh broadcasted syncshells.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (updatedList == null || updatedList.Count == 0)
|
||||
{
|
||||
ClearSyncshells();
|
||||
return;
|
||||
}
|
||||
|
||||
List<GroupJoinDto>? updatedList = [];
|
||||
try
|
||||
if (gid != null && _recentlyJoined.Contains(gid))
|
||||
{
|
||||
var groups = await _apiController.GetBroadcastedGroups(syncshellBroadcasts).ConfigureAwait(false);
|
||||
updatedList = groups?.ToList();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to refresh broadcasted syncshells.");
|
||||
return;
|
||||
_recentlyJoined.Clear();
|
||||
}
|
||||
|
||||
if (updatedList != null)
|
||||
var previousGid = GetSelectedGid();
|
||||
|
||||
_nearbySyncshells.Clear();
|
||||
_nearbySyncshells.AddRange(updatedList);
|
||||
|
||||
if (previousGid != null)
|
||||
{
|
||||
var previousGid = GetSelectedGid();
|
||||
var newIndex = _nearbySyncshells.FindIndex(s =>
|
||||
string.Equals(s.Group.GID, previousGid, StringComparison.Ordinal));
|
||||
|
||||
_nearbySyncshells.Clear();
|
||||
_nearbySyncshells.AddRange(updatedList);
|
||||
|
||||
if (previousGid != null)
|
||||
if (newIndex >= 0)
|
||||
{
|
||||
var newIndex = _nearbySyncshells.FindIndex(s => string.Equals(s.Group.GID, previousGid, StringComparison.Ordinal));
|
||||
if (newIndex >= 0)
|
||||
{
|
||||
_selectedNearbyIndex = newIndex;
|
||||
return;
|
||||
}
|
||||
_selectedNearbyIndex = newIndex;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ClearSelection();
|
||||
}
|
||||
|
||||
private List<GroupJoinDto> BuildTestSyncshells()
|
||||
{
|
||||
var testGroup1 = new GroupData("TEST-ALPHA", "Alpha Shell");
|
||||
var testGroup2 = new GroupData("TEST-BETA", "Beta Shell");
|
||||
var testGroup3 = new GroupData("TEST-GAMMA", "Gamma Shell");
|
||||
var testGroup4 = new GroupData("TEST-DELTA", "Delta Shell");
|
||||
var testGroup5 = new GroupData("TEST-CHARLIE", "Charlie Shell");
|
||||
var testGroup6 = new GroupData("TEST-OMEGA", "Omega Shell");
|
||||
var testGroup7 = new GroupData("TEST-POINT", "Point Shell");
|
||||
var testGroup8 = new GroupData("TEST-HOTEL", "Hotel Shell");
|
||||
|
||||
return
|
||||
[
|
||||
new(testGroup1, "", GroupUserPreferredPermissions.NoneSet),
|
||||
new(testGroup2, "", GroupUserPreferredPermissions.NoneSet),
|
||||
new(testGroup3, "", GroupUserPreferredPermissions.NoneSet),
|
||||
new(testGroup4, "", GroupUserPreferredPermissions.NoneSet),
|
||||
new(testGroup5, "", GroupUserPreferredPermissions.NoneSet),
|
||||
new(testGroup6, "", GroupUserPreferredPermissions.NoneSet),
|
||||
new(testGroup7, "", GroupUserPreferredPermissions.NoneSet),
|
||||
new(testGroup8, "", GroupUserPreferredPermissions.NoneSet),
|
||||
];
|
||||
}
|
||||
|
||||
private void ClearSyncshells()
|
||||
{
|
||||
if (_nearbySyncshells.Count == 0)
|
||||
@@ -322,6 +574,7 @@ public class SyncshellFinderUI : WindowMediatorSubscriberBase
|
||||
private void ClearSelection()
|
||||
{
|
||||
_selectedNearbyIndex = -1;
|
||||
_syncshellPageIndex = 0;
|
||||
_joinDto = null;
|
||||
_joinInfo = null;
|
||||
}
|
||||
|
||||
@@ -123,133 +123,133 @@ public class TopTabMenu
|
||||
}
|
||||
UiSharedService.AttachToolTip("Individual Pair Menu");
|
||||
|
||||
using (ImRaii.PushFont(UiBuilder.IconFont))
|
||||
{
|
||||
var x = ImGui.GetCursorScreenPos();
|
||||
if (ImGui.Button(FontAwesomeIcon.Users.ToIconString(), buttonSize))
|
||||
using (ImRaii.PushFont(UiBuilder.IconFont))
|
||||
{
|
||||
TabSelection = TabSelection == SelectedTab.Syncshell ? SelectedTab.None : SelectedTab.Syncshell;
|
||||
var x = ImGui.GetCursorScreenPos();
|
||||
if (ImGui.Button(FontAwesomeIcon.Users.ToIconString(), buttonSize))
|
||||
{
|
||||
TabSelection = TabSelection == SelectedTab.Syncshell ? SelectedTab.None : SelectedTab.Syncshell;
|
||||
}
|
||||
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenBlockedByActiveItem) || ImGui.IsItemActive())
|
||||
{
|
||||
Selune.RegisterHighlight(ImGui.GetItemRectMin(), ImGui.GetItemRectMax(), SeluneHighlightMode.Both, true, buttonBorderThickness, exactSize: true, clipToElement: true, roundingOverride: buttonRounding);
|
||||
}
|
||||
ImGui.SameLine();
|
||||
var xAfter = ImGui.GetCursorScreenPos();
|
||||
if (TabSelection == SelectedTab.Syncshell)
|
||||
drawList.AddLine(x with { Y = x.Y + buttonSize.Y + spacing.Y },
|
||||
xAfter with { Y = xAfter.Y + buttonSize.Y + spacing.Y, X = xAfter.X - spacing.X },
|
||||
underlineColor, 2);
|
||||
}
|
||||
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenBlockedByActiveItem) || ImGui.IsItemActive())
|
||||
UiSharedService.AttachToolTip("Syncshell Menu");
|
||||
|
||||
using (ImRaii.PushFont(UiBuilder.IconFont))
|
||||
{
|
||||
Selune.RegisterHighlight(ImGui.GetItemRectMin(), ImGui.GetItemRectMax(), SeluneHighlightMode.Both, true, buttonBorderThickness, exactSize: true, clipToElement: true, roundingOverride: buttonRounding);
|
||||
if (ImGui.Button(FontAwesomeIcon.Comments.ToIconString(), buttonSize))
|
||||
{
|
||||
_lightlessMediator.Publish(new UiToggleMessage(typeof(ZoneChatUi)));
|
||||
}
|
||||
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenBlockedByActiveItem) || ImGui.IsItemActive())
|
||||
{
|
||||
Selune.RegisterHighlight(ImGui.GetItemRectMin(), ImGui.GetItemRectMax(), SeluneHighlightMode.Both, true, buttonBorderThickness, exactSize: true, clipToElement: true, roundingOverride: buttonRounding);
|
||||
}
|
||||
}
|
||||
UiSharedService.AttachToolTip("Zone Chat");
|
||||
ImGui.SameLine();
|
||||
var xAfter = ImGui.GetCursorScreenPos();
|
||||
if (TabSelection == SelectedTab.Syncshell)
|
||||
drawList.AddLine(x with { Y = x.Y + buttonSize.Y + spacing.Y },
|
||||
xAfter with { Y = xAfter.Y + buttonSize.Y + spacing.Y, X = xAfter.X - spacing.X },
|
||||
underlineColor, 2);
|
||||
}
|
||||
UiSharedService.AttachToolTip("Syncshell Menu");
|
||||
|
||||
using (ImRaii.PushFont(UiBuilder.IconFont))
|
||||
{
|
||||
if (ImGui.Button(FontAwesomeIcon.Comments.ToIconString(), buttonSize))
|
||||
{
|
||||
_lightlessMediator.Publish(new UiToggleMessage(typeof(ZoneChatUi)));
|
||||
}
|
||||
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenBlockedByActiveItem) || ImGui.IsItemActive())
|
||||
{
|
||||
Selune.RegisterHighlight(ImGui.GetItemRectMin(), ImGui.GetItemRectMax(), SeluneHighlightMode.Both, true, buttonBorderThickness, exactSize: true, clipToElement: true, roundingOverride: buttonRounding);
|
||||
}
|
||||
}
|
||||
UiSharedService.AttachToolTip("Zone Chat");
|
||||
ImGui.SameLine();
|
||||
|
||||
ImGui.SameLine();
|
||||
using (ImRaii.PushFont(UiBuilder.IconFont))
|
||||
{
|
||||
var x = ImGui.GetCursorScreenPos();
|
||||
if (ImGui.Button(FontAwesomeIcon.Compass.ToIconString(), buttonSize))
|
||||
{
|
||||
TabSelection = TabSelection == SelectedTab.Lightfinder ? SelectedTab.None : SelectedTab.Lightfinder;
|
||||
}
|
||||
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenBlockedByActiveItem) || ImGui.IsItemActive())
|
||||
{
|
||||
Selune.RegisterHighlight(ImGui.GetItemRectMin(), ImGui.GetItemRectMax(), SeluneHighlightMode.Both, true, buttonBorderThickness, exactSize: true, clipToElement: true, roundingOverride: buttonRounding);
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
var xAfter = ImGui.GetCursorScreenPos();
|
||||
if (TabSelection == SelectedTab.Lightfinder)
|
||||
drawList.AddLine(x with { Y = x.Y + buttonSize.Y + spacing.Y },
|
||||
xAfter with { Y = xAfter.Y + buttonSize.Y + spacing.Y, X = xAfter.X - spacing.X },
|
||||
underlineColor, 2);
|
||||
}
|
||||
UiSharedService.AttachToolTip("Lightfinder");
|
||||
using (ImRaii.PushFont(UiBuilder.IconFont))
|
||||
{
|
||||
var x = ImGui.GetCursorScreenPos();
|
||||
if (ImGui.Button(FontAwesomeIcon.Compass.ToIconString(), buttonSize))
|
||||
{
|
||||
TabSelection = TabSelection == SelectedTab.Lightfinder ? SelectedTab.None : SelectedTab.Lightfinder;
|
||||
}
|
||||
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenBlockedByActiveItem) || ImGui.IsItemActive())
|
||||
{
|
||||
Selune.RegisterHighlight(ImGui.GetItemRectMin(), ImGui.GetItemRectMax(), SeluneHighlightMode.Both, true, buttonBorderThickness, exactSize: true, clipToElement: true, roundingOverride: buttonRounding);
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
using (ImRaii.PushFont(UiBuilder.IconFont))
|
||||
{
|
||||
var x = ImGui.GetCursorScreenPos();
|
||||
if (ImGui.Button(FontAwesomeIcon.UserCog.ToIconString(), buttonSize))
|
||||
{
|
||||
TabSelection = TabSelection == SelectedTab.UserConfig ? SelectedTab.None : SelectedTab.UserConfig;
|
||||
}
|
||||
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenBlockedByActiveItem) || ImGui.IsItemActive())
|
||||
{
|
||||
Selune.RegisterHighlight(ImGui.GetItemRectMin(), ImGui.GetItemRectMax(), SeluneHighlightMode.Both, true, buttonBorderThickness, exactSize: true, clipToElement: true, roundingOverride: buttonRounding);
|
||||
ImGui.SameLine();
|
||||
var xAfter = ImGui.GetCursorScreenPos();
|
||||
if (TabSelection == SelectedTab.Lightfinder)
|
||||
drawList.AddLine(x with { Y = x.Y + buttonSize.Y + spacing.Y },
|
||||
xAfter with { Y = xAfter.Y + buttonSize.Y + spacing.Y, X = xAfter.X - spacing.X },
|
||||
underlineColor, 2);
|
||||
}
|
||||
UiSharedService.AttachToolTip("Lightfinder");
|
||||
|
||||
ImGui.SameLine();
|
||||
var xAfter = ImGui.GetCursorScreenPos();
|
||||
if (TabSelection == SelectedTab.UserConfig)
|
||||
drawList.AddLine(x with { Y = x.Y + buttonSize.Y + spacing.Y },
|
||||
xAfter with { Y = xAfter.Y + buttonSize.Y + spacing.Y, X = xAfter.X - spacing.X },
|
||||
underlineColor, 2);
|
||||
}
|
||||
UiSharedService.AttachToolTip("Your User Menu");
|
||||
using (ImRaii.PushFont(UiBuilder.IconFont))
|
||||
{
|
||||
var x = ImGui.GetCursorScreenPos();
|
||||
if (ImGui.Button(FontAwesomeIcon.UserCog.ToIconString(), buttonSize))
|
||||
{
|
||||
TabSelection = TabSelection == SelectedTab.UserConfig ? SelectedTab.None : SelectedTab.UserConfig;
|
||||
}
|
||||
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenBlockedByActiveItem) || ImGui.IsItemActive())
|
||||
{
|
||||
Selune.RegisterHighlight(ImGui.GetItemRectMin(), ImGui.GetItemRectMax(), SeluneHighlightMode.Both, true, buttonBorderThickness, exactSize: true, clipToElement: true, roundingOverride: buttonRounding);
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
using (ImRaii.PushFont(UiBuilder.IconFont))
|
||||
{
|
||||
var x = ImGui.GetCursorScreenPos();
|
||||
if (ImGui.Button(FontAwesomeIcon.Cog.ToIconString(), buttonSize))
|
||||
{
|
||||
_lightlessMediator.Publish(new UiToggleMessage(typeof(SettingsUi)));
|
||||
}
|
||||
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenBlockedByActiveItem) || ImGui.IsItemActive())
|
||||
{
|
||||
Selune.RegisterHighlight(ImGui.GetItemRectMin(), ImGui.GetItemRectMax(), SeluneHighlightMode.Both, true, buttonBorderThickness, exactSize: true, clipToElement: true, roundingOverride: buttonRounding);
|
||||
ImGui.SameLine();
|
||||
var xAfter = ImGui.GetCursorScreenPos();
|
||||
if (TabSelection == SelectedTab.UserConfig)
|
||||
drawList.AddLine(x with { Y = x.Y + buttonSize.Y + spacing.Y },
|
||||
xAfter with { Y = xAfter.Y + buttonSize.Y + spacing.Y, X = xAfter.X - spacing.X },
|
||||
underlineColor, 2);
|
||||
}
|
||||
UiSharedService.AttachToolTip("Your User Menu");
|
||||
|
||||
ImGui.SameLine();
|
||||
using (ImRaii.PushFont(UiBuilder.IconFont))
|
||||
{
|
||||
var x = ImGui.GetCursorScreenPos();
|
||||
if (ImGui.Button(FontAwesomeIcon.Cog.ToIconString(), buttonSize))
|
||||
{
|
||||
_lightlessMediator.Publish(new UiToggleMessage(typeof(SettingsUi)));
|
||||
}
|
||||
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenBlockedByActiveItem) || ImGui.IsItemActive())
|
||||
{
|
||||
Selune.RegisterHighlight(ImGui.GetItemRectMin(), ImGui.GetItemRectMax(), SeluneHighlightMode.Both, true, buttonBorderThickness, exactSize: true, clipToElement: true, roundingOverride: buttonRounding);
|
||||
}
|
||||
ImGui.SameLine();
|
||||
}
|
||||
UiSharedService.AttachToolTip("Open Lightless Settings");
|
||||
|
||||
ImGui.NewLine();
|
||||
btncolor.Dispose();
|
||||
|
||||
ImGuiHelpers.ScaledDummy(spacing);
|
||||
|
||||
if (TabSelection == SelectedTab.Individual)
|
||||
{
|
||||
DrawAddPair(availableWidth, spacing.X);
|
||||
DrawGlobalIndividualButtons(availableWidth, spacing.X);
|
||||
}
|
||||
else if (TabSelection == SelectedTab.Syncshell)
|
||||
{
|
||||
DrawSyncshellMenu(availableWidth, spacing.X);
|
||||
DrawGlobalSyncshellButtons(availableWidth, spacing.X);
|
||||
}
|
||||
else if (TabSelection == SelectedTab.Lightfinder)
|
||||
{
|
||||
DrawLightfinderMenu(availableWidth, spacing.X);
|
||||
}
|
||||
else if (TabSelection == SelectedTab.UserConfig)
|
||||
{
|
||||
DrawUserConfig(availableWidth, spacing.X);
|
||||
}
|
||||
|
||||
if (TabSelection != SelectedTab.None) ImGuiHelpers.ScaledDummy(3f);
|
||||
|
||||
|
||||
DrawIncomingPairRequests(availableWidth);
|
||||
|
||||
ImGui.Separator();
|
||||
|
||||
DrawFilter(availableWidth, spacing.X);
|
||||
}
|
||||
UiSharedService.AttachToolTip("Open Lightless Settings");
|
||||
|
||||
ImGui.NewLine();
|
||||
btncolor.Dispose();
|
||||
|
||||
ImGuiHelpers.ScaledDummy(spacing);
|
||||
|
||||
if (TabSelection == SelectedTab.Individual)
|
||||
{
|
||||
DrawAddPair(availableWidth, spacing.X);
|
||||
DrawGlobalIndividualButtons(availableWidth, spacing.X);
|
||||
}
|
||||
else if (TabSelection == SelectedTab.Syncshell)
|
||||
{
|
||||
DrawSyncshellMenu(availableWidth, spacing.X);
|
||||
DrawGlobalSyncshellButtons(availableWidth, spacing.X);
|
||||
}
|
||||
else if (TabSelection == SelectedTab.Lightfinder)
|
||||
{
|
||||
DrawLightfinderMenu(availableWidth, spacing.X);
|
||||
}
|
||||
else if (TabSelection == SelectedTab.UserConfig)
|
||||
{
|
||||
DrawUserConfig(availableWidth, spacing.X);
|
||||
}
|
||||
|
||||
if (TabSelection != SelectedTab.None) ImGuiHelpers.ScaledDummy(3f);
|
||||
|
||||
|
||||
DrawIncomingPairRequests(availableWidth);
|
||||
|
||||
ImGui.Separator();
|
||||
|
||||
DrawFilter(availableWidth, spacing.X);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_currentSnapshot = null;
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace LightlessSync.UI
|
||||
return HexToRgba(customColorHex);
|
||||
|
||||
if (!DefaultHexColors.TryGetValue(name, out var hex))
|
||||
throw new ArgumentException($"Color '{name}' not found in UIColors.");
|
||||
throw new ArgumentException($"Color '{name}' not found in UIColors.", nameof(name));
|
||||
|
||||
return HexToRgba(hex);
|
||||
}
|
||||
@@ -53,7 +53,7 @@ namespace LightlessSync.UI
|
||||
public static void Set(string name, Vector4 color)
|
||||
{
|
||||
if (!DefaultHexColors.ContainsKey(name))
|
||||
throw new ArgumentException($"Color '{name}' not found in UIColors.");
|
||||
throw new ArgumentException($"Color '{name}' not found in UIColors.", nameof(name));
|
||||
|
||||
if (_configService != null)
|
||||
{
|
||||
@@ -83,7 +83,7 @@ namespace LightlessSync.UI
|
||||
public static Vector4 GetDefault(string name)
|
||||
{
|
||||
if (!DefaultHexColors.TryGetValue(name, out var hex))
|
||||
throw new ArgumentException($"Color '{name}' not found in UIColors.");
|
||||
throw new ArgumentException($"Color '{name}' not found in UIColors.", nameof(name));
|
||||
|
||||
return HexToRgba(hex);
|
||||
}
|
||||
@@ -101,10 +101,10 @@ namespace LightlessSync.UI
|
||||
public static Vector4 HexToRgba(string hexColor)
|
||||
{
|
||||
hexColor = hexColor.TrimStart('#');
|
||||
int r = int.Parse(hexColor.Substring(0, 2), NumberStyles.HexNumber);
|
||||
int g = int.Parse(hexColor.Substring(2, 2), NumberStyles.HexNumber);
|
||||
int b = int.Parse(hexColor.Substring(4, 2), NumberStyles.HexNumber);
|
||||
int a = hexColor.Length == 8 ? int.Parse(hexColor.Substring(6, 2), NumberStyles.HexNumber) : 255;
|
||||
int r = int.Parse(hexColor[..2], NumberStyles.HexNumber);
|
||||
int g = int.Parse(hexColor[2..4], NumberStyles.HexNumber);
|
||||
int b = int.Parse(hexColor[4..6], NumberStyles.HexNumber);
|
||||
int a = hexColor.Length == 8 ? int.Parse(hexColor[6..8], NumberStyles.HexNumber) : 255;
|
||||
return new Vector4(r / 255f, g / 255f, b / 255f, a / 255f);
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
|
||||
private bool _isOneDrive = false;
|
||||
private bool _isPenumbraDirectory = false;
|
||||
private bool _moodlesExists = false;
|
||||
private Dictionary<string, DateTime> _oauthTokenExpiry = new();
|
||||
private readonly Dictionary<string, DateTime> _oauthTokenExpiry = [];
|
||||
private bool _penumbraExists = false;
|
||||
private bool _petNamesExists = false;
|
||||
private int _serverSelectionIndex = -1;
|
||||
@@ -487,7 +487,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
|
||||
);
|
||||
}
|
||||
|
||||
public void ColoredSeparator(Vector4? color = null, float thickness = 1f, float indent = 0f)
|
||||
public static void ColoredSeparator(Vector4? color = null, float thickness = 1f, float indent = 0f)
|
||||
{
|
||||
var drawList = ImGui.GetWindowDrawList();
|
||||
var min = ImGui.GetCursorScreenPos();
|
||||
@@ -1080,7 +1080,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
|
||||
{
|
||||
using (ImRaii.Disabled(_discordOAuthUIDs == null))
|
||||
{
|
||||
var aliasPairs = _discordOAuthUIDs?.Result?.Select(t => new UIDAliasPair(t.Key, t.Value)).ToList() ?? [new UIDAliasPair(item.UID ?? null, null)];
|
||||
var aliasPairs = _discordOAuthUIDs?.Result?.Select(t => new UidAliasPair(t.Key, t.Value)).ToList() ?? [new UidAliasPair(item.UID ?? null, null)];
|
||||
var uidComboName = "UID###" + item.CharacterName + item.WorldId + serverUri + indexOffset + aliasPairs.Count;
|
||||
DrawCombo(uidComboName, aliasPairs,
|
||||
(v) =>
|
||||
@@ -1360,6 +1360,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
|
||||
UidFont.Dispose();
|
||||
GameFont.Dispose();
|
||||
MediumFont.Dispose();
|
||||
_discordOAuthGetCts.Dispose();
|
||||
}
|
||||
|
||||
private static void CenterWindow(float width, float height, ImGuiCond cond = ImGuiCond.None)
|
||||
@@ -1443,6 +1444,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public sealed record IconScaleData(Vector2 IconSize, Vector2 NormalizedIconScale, float OffsetX, float IconScaling);
|
||||
private record UIDAliasPair(string? UID, string? Alias);
|
||||
private sealed record UidAliasPair(string? UID, string? Alias);
|
||||
}
|
||||
@@ -25,7 +25,6 @@ public class UpdateNotesUi : WindowMediatorSubscriberBase
|
||||
private ChangelogFile _changelog = new();
|
||||
private CreditsFile _credits = new();
|
||||
private bool _scrollToTop;
|
||||
private int _selectedTab;
|
||||
private bool _hasInitializedCollapsingHeaders;
|
||||
|
||||
private struct Particle
|
||||
@@ -160,7 +159,7 @@ public class UpdateNotesUi : WindowMediatorSubscriberBase
|
||||
DrawParticleEffects(headerStart, extendedParticleSize);
|
||||
}
|
||||
|
||||
private void DrawGradientBackground(Vector2 headerStart, Vector2 headerEnd)
|
||||
private static void DrawGradientBackground(Vector2 headerStart, Vector2 headerEnd)
|
||||
{
|
||||
var drawList = ImGui.GetWindowDrawList();
|
||||
|
||||
@@ -188,7 +187,7 @@ public class UpdateNotesUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawBottomGradient(Vector2 headerStart, Vector2 headerEnd, float width)
|
||||
private static void DrawBottomGradient(Vector2 headerStart, Vector2 headerEnd, float width)
|
||||
{
|
||||
var drawList = ImGui.GetWindowDrawList();
|
||||
var gradientHeight = 60f;
|
||||
@@ -513,7 +512,6 @@ public class UpdateNotesUi : WindowMediatorSubscriberBase
|
||||
{
|
||||
if (changelogTab)
|
||||
{
|
||||
_selectedTab = 0;
|
||||
DrawChangelog();
|
||||
}
|
||||
}
|
||||
@@ -524,7 +522,6 @@ public class UpdateNotesUi : WindowMediatorSubscriberBase
|
||||
{
|
||||
if (creditsTab)
|
||||
{
|
||||
_selectedTab = 1;
|
||||
DrawCredits();
|
||||
}
|
||||
}
|
||||
@@ -558,7 +555,7 @@ public class UpdateNotesUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawCreditCategory(CreditCategory category)
|
||||
private static void DrawCreditCategory(CreditCategory category)
|
||||
{
|
||||
DrawFeatureSection(category.Category, UIColors.Get("LightlessBlue"));
|
||||
|
||||
@@ -745,7 +742,7 @@ public class UpdateNotesUi : WindowMediatorSubscriberBase
|
||||
using var changelogStream = assembly.GetManifestResourceStream("LightlessSync.Changelog.changelog.yaml");
|
||||
if (changelogStream != null)
|
||||
{
|
||||
using var reader = new StreamReader(changelogStream, Encoding.UTF8, true, 128);
|
||||
using var reader = new StreamReader(changelogStream, Encoding.UTF8, detectEncodingFromByteOrderMarks: true, 128);
|
||||
var yaml = reader.ReadToEnd();
|
||||
_changelog = deserializer.Deserialize<ChangelogFile>(yaml) ?? new();
|
||||
}
|
||||
@@ -754,7 +751,7 @@ public class UpdateNotesUi : WindowMediatorSubscriberBase
|
||||
using var creditsStream = assembly.GetManifestResourceStream("LightlessSync.Changelog.credits.yaml");
|
||||
if (creditsStream != null)
|
||||
{
|
||||
using var reader = new StreamReader(creditsStream, Encoding.UTF8, true, 128);
|
||||
using var reader = new StreamReader(creditsStream, Encoding.UTF8, detectEncodingFromByteOrderMarks: true, 128);
|
||||
var yaml = reader.ReadToEnd();
|
||||
_credits = deserializer.Deserialize<CreditsFile>(yaml) ?? new();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user