Fixed migration for 2.0.0
This commit is contained in:
@@ -259,6 +259,9 @@ public sealed class CacheMonitor : DisposableMediatorSubscriberBase
|
|||||||
|
|
||||||
private CancellationTokenSource _penumbraFswCts = new();
|
private CancellationTokenSource _penumbraFswCts = new();
|
||||||
private CancellationTokenSource _lightlessFswCts = new();
|
private CancellationTokenSource _lightlessFswCts = new();
|
||||||
|
private long totalSize;
|
||||||
|
private long maxCacheBytes;
|
||||||
|
|
||||||
public FileSystemWatcher? PenumbraWatcher { get; private set; }
|
public FileSystemWatcher? PenumbraWatcher { get; private set; }
|
||||||
public FileSystemWatcher? LightlessWatcher { get; private set; }
|
public FileSystemWatcher? LightlessWatcher { get; private set; }
|
||||||
|
|
||||||
@@ -485,7 +488,7 @@ public sealed class CacheMonitor : DisposableMediatorSubscriberBase
|
|||||||
{
|
{
|
||||||
long size = 0;
|
long size = 0;
|
||||||
|
|
||||||
if (!isWine)
|
if (!_dalamudUtil.IsWine)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ public sealed partial class FileCompactor : IDisposable
|
|||||||
public const uint FSCTL_DELETE_EXTERNAL_BACKING = 0x90314U;
|
public const uint FSCTL_DELETE_EXTERNAL_BACKING = 0x90314U;
|
||||||
public const ulong WOF_PROVIDER_FILE = 2UL;
|
public const ulong WOF_PROVIDER_FILE = 2UL;
|
||||||
public const int _maxRetries = 3;
|
public const int _maxRetries = 3;
|
||||||
private readonly bool _isWindows;
|
|
||||||
|
|
||||||
private readonly ConcurrentDictionary<string, byte> _pendingCompactions;
|
private readonly ConcurrentDictionary<string, byte> _pendingCompactions;
|
||||||
private readonly ILogger<FileCompactor> _logger;
|
private readonly ILogger<FileCompactor> _logger;
|
||||||
@@ -272,9 +271,6 @@ public sealed partial class FileCompactor : IDisposable
|
|||||||
? RunProcessShell($"stat -c='%b' {QuoteSingle(linuxPath)}", workingDir: null, 10000)
|
? RunProcessShell($"stat -c='%b' {QuoteSingle(linuxPath)}", workingDir: null, 10000)
|
||||||
: RunProcessDirect("stat", ["-c='%b'", linuxPath], workingDir: null, 10000);
|
: RunProcessDirect("stat", ["-c='%b'", linuxPath], workingDir: null, 10000);
|
||||||
|
|
||||||
if (_logger.IsEnabled(LogLevel.Debug))
|
|
||||||
_logger.LogDebug("Btrfs size probe failed for {linux} (exit {code}). stdout='{so}' stderr='{se}'. Falling back to Length.", linuxPath, res.code, outTrim, (res.se ?? "").Trim());
|
|
||||||
|
|
||||||
return (flowControl: false, value: fileInfo.Length);
|
return (flowControl: false, value: fileInfo.Length);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -1160,6 +1156,11 @@ public sealed partial class FileCompactor : IDisposable
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogTrace(ex, "Probe open failed for {file} (linux={linux})", winePath, linuxPath);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -288,7 +288,7 @@ public sealed class Plugin : IDalamudPlugin
|
|||||||
clientState,
|
clientState,
|
||||||
sp.GetRequiredService<LightlessMediator>()));
|
sp.GetRequiredService<LightlessMediator>()));
|
||||||
collection.AddSingleton<HubFactory>();
|
collection.AddSingleton<HubFactory>();
|
||||||
collection.AddSingleton(s => new BroadcastScannerService( s.GetRequiredService<ILogger<BroadcastScannerService>>(), framework, s.GetRequiredService<BroadcastService>(), s.GetRequiredService<LightlessMediator>(), s.GetRequiredService<NameplateHandler>(), s.GetRequiredService<ActorObjectService>()));
|
collection.AddSingleton(s => new BroadcastScannerService(s.GetRequiredService<ILogger<BroadcastScannerService>>(), framework, s.GetRequiredService<BroadcastService>(), s.GetRequiredService<LightlessMediator>(), s.GetRequiredService<NameplateHandler>(), s.GetRequiredService<ActorObjectService>()));
|
||||||
|
|
||||||
|
|
||||||
// add scoped services
|
// add scoped services
|
||||||
@@ -342,7 +342,7 @@ public sealed class Plugin : IDalamudPlugin
|
|||||||
s.GetRequiredService<LightlessMediator>()));
|
s.GetRequiredService<LightlessMediator>()));
|
||||||
collection.AddScoped((s) => new NameplateService(s.GetRequiredService<ILogger<NameplateService>>(), s.GetRequiredService<LightlessConfigService>(), clientState, gameGui, objectTable, gameInteropProvider,
|
collection.AddScoped((s) => new NameplateService(s.GetRequiredService<ILogger<NameplateService>>(), s.GetRequiredService<LightlessConfigService>(), clientState, gameGui, objectTable, gameInteropProvider,
|
||||||
s.GetRequiredService<LightlessMediator>(),s.GetRequiredService<PairUiService>()));
|
s.GetRequiredService<LightlessMediator>(),s.GetRequiredService<PairUiService>()));
|
||||||
collection.AddScoped((s) => new NameplateHandler(s.GetRequiredService<ILogger<NameplateHandler>>(), addonLifecycle, gameGui, s.GetRequiredService<DalamudUtilService>(),
|
collection.AddScoped((s) => new NameplateHandler(s.GetRequiredService<ILogger<NameplateHandler>>(), addonLifecycle, gameGui,
|
||||||
s.GetRequiredService<LightlessConfigService>(), s.GetRequiredService<LightlessMediator>(), clientState, s.GetRequiredService<PairUiService>()));
|
s.GetRequiredService<LightlessConfigService>(), s.GetRequiredService<LightlessMediator>(), clientState, s.GetRequiredService<PairUiService>()));
|
||||||
|
|
||||||
collection.AddHostedService(p => p.GetRequiredService<ConfigurationSaveService>());
|
collection.AddHostedService(p => p.GetRequiredService<ConfigurationSaveService>());
|
||||||
|
|||||||
@@ -21,16 +21,16 @@ public class BroadcastScannerService : DisposableMediatorSubscriberBase
|
|||||||
private readonly HashSet<string> _lookupQueuedCids = [];
|
private readonly HashSet<string> _lookupQueuedCids = [];
|
||||||
private readonly HashSet<string> _syncshellCids = [];
|
private readonly HashSet<string> _syncshellCids = [];
|
||||||
|
|
||||||
private static readonly TimeSpan MaxAllowedTtl = TimeSpan.FromMinutes(4);
|
private static readonly TimeSpan _maxAllowedTtl = TimeSpan.FromMinutes(4);
|
||||||
private static readonly TimeSpan RetryDelay = TimeSpan.FromMinutes(1);
|
private static readonly TimeSpan _retryDelay = TimeSpan.FromMinutes(1);
|
||||||
|
|
||||||
private readonly CancellationTokenSource _cleanupCts = new();
|
private readonly CancellationTokenSource _cleanupCts = new();
|
||||||
private readonly Task? _cleanupTask;
|
private readonly Task? _cleanupTask;
|
||||||
|
|
||||||
private readonly int _checkEveryFrames = 20;
|
private readonly int _checkEveryFrames = 20;
|
||||||
private int _frameCounter = 0;
|
private int _frameCounter = 0;
|
||||||
private const int MaxLookupsPerFrame = 30;
|
private const int _maxLookupsPerFrame = 30;
|
||||||
private const int MaxQueueSize = 100;
|
private const int _maxQueueSize = 100;
|
||||||
|
|
||||||
private volatile bool _batchRunning = false;
|
private volatile bool _batchRunning = false;
|
||||||
|
|
||||||
@@ -38,11 +38,11 @@ public class BroadcastScannerService : DisposableMediatorSubscriberBase
|
|||||||
public readonly record struct BroadcastEntry(bool IsBroadcasting, DateTime ExpiryTime, string? GID);
|
public readonly record struct BroadcastEntry(bool IsBroadcasting, DateTime ExpiryTime, string? GID);
|
||||||
|
|
||||||
public BroadcastScannerService(ILogger<BroadcastScannerService> logger,
|
public BroadcastScannerService(ILogger<BroadcastScannerService> logger,
|
||||||
IObjectTable objectTable,
|
|
||||||
IFramework framework,
|
IFramework framework,
|
||||||
BroadcastService broadcastService,
|
BroadcastService broadcastService,
|
||||||
LightlessMediator mediator,
|
LightlessMediator mediator,
|
||||||
NameplateHandler nameplateHandler) : base(logger, mediator)
|
NameplateHandler nameplateHandler,
|
||||||
|
ActorObjectService actorTracker) : base(logger, mediator)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_actorTracker = actorTracker;
|
_actorTracker = actorTracker;
|
||||||
@@ -57,6 +57,7 @@ public class BroadcastScannerService : DisposableMediatorSubscriberBase
|
|||||||
_cleanupTask = Task.Run(ExpiredBroadcastCleanupLoop);
|
_cleanupTask = Task.Run(ExpiredBroadcastCleanupLoop);
|
||||||
|
|
||||||
_nameplateHandler.Init();
|
_nameplateHandler.Init();
|
||||||
|
_actorTracker = actorTracker;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnFrameworkUpdate(IFramework framework) => Update();
|
private void OnFrameworkUpdate(IFramework framework) => Update();
|
||||||
@@ -79,14 +80,14 @@ public class BroadcastScannerService : DisposableMediatorSubscriberBase
|
|||||||
var cid = DalamudUtilService.GetHashedCIDFromPlayerPointer(address);
|
var cid = DalamudUtilService.GetHashedCIDFromPlayerPointer(address);
|
||||||
var isStale = !_broadcastCache.TryGetValue(cid, out var entry) || entry.ExpiryTime <= now;
|
var isStale = !_broadcastCache.TryGetValue(cid, out var entry) || entry.ExpiryTime <= now;
|
||||||
|
|
||||||
if (isStale && _lookupQueuedCids.Add(cid) && _lookupQueue.Count < MaxQueueSize)
|
if (isStale && _lookupQueuedCids.Add(cid) && _lookupQueue.Count < _maxQueueSize)
|
||||||
_lookupQueue.Enqueue(cid);
|
_lookupQueue.Enqueue(cid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_frameCounter % _checkEveryFrames == 0 && _lookupQueue.Count > 0)
|
if (_frameCounter % _checkEveryFrames == 0 && _lookupQueue.Count > 0)
|
||||||
{
|
{
|
||||||
var cidsToLookup = new List<string>();
|
var cidsToLookup = new List<string>();
|
||||||
while (_lookupQueue.Count > 0 && lookupsThisFrame < MaxLookupsPerFrame)
|
while (_lookupQueue.Count > 0 && lookupsThisFrame < _maxLookupsPerFrame)
|
||||||
{
|
{
|
||||||
var cid = _lookupQueue.Dequeue();
|
var cid = _lookupQueue.Dequeue();
|
||||||
_lookupQueuedCids.Remove(cid);
|
_lookupQueuedCids.Remove(cid);
|
||||||
@@ -113,8 +114,8 @@ public class BroadcastScannerService : DisposableMediatorSubscriberBase
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
var ttl = info.IsBroadcasting && info.TTL.HasValue
|
var ttl = info.IsBroadcasting && info.TTL.HasValue
|
||||||
? TimeSpan.FromTicks(Math.Min(info.TTL.Value.Ticks, MaxAllowedTtl.Ticks))
|
? TimeSpan.FromTicks(Math.Min(info.TTL.Value.Ticks, _maxAllowedTtl.Ticks))
|
||||||
: RetryDelay;
|
: _retryDelay;
|
||||||
|
|
||||||
var expiry = now + ttl;
|
var expiry = now + ttl;
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -22,7 +22,6 @@ public class UiFactory
|
|||||||
private readonly ServerConfigurationManager _serverConfigManager;
|
private readonly ServerConfigurationManager _serverConfigManager;
|
||||||
private readonly LightlessProfileManager _lightlessProfileManager;
|
private readonly LightlessProfileManager _lightlessProfileManager;
|
||||||
private readonly PerformanceCollectorService _performanceCollectorService;
|
private readonly PerformanceCollectorService _performanceCollectorService;
|
||||||
private readonly FileDialogManager _fileDialogManager;
|
|
||||||
private readonly ProfileTagService _profileTagService;
|
private readonly ProfileTagService _profileTagService;
|
||||||
|
|
||||||
public UiFactory(
|
public UiFactory(
|
||||||
@@ -34,7 +33,6 @@ public class UiFactory
|
|||||||
ServerConfigurationManager serverConfigManager,
|
ServerConfigurationManager serverConfigManager,
|
||||||
LightlessProfileManager lightlessProfileManager,
|
LightlessProfileManager lightlessProfileManager,
|
||||||
PerformanceCollectorService performanceCollectorService,
|
PerformanceCollectorService performanceCollectorService,
|
||||||
FileDialogManager fileDialogManager,
|
|
||||||
ProfileTagService profileTagService)
|
ProfileTagService profileTagService)
|
||||||
{
|
{
|
||||||
_loggerFactory = loggerFactory;
|
_loggerFactory = loggerFactory;
|
||||||
@@ -45,7 +43,6 @@ public class UiFactory
|
|||||||
_serverConfigManager = serverConfigManager;
|
_serverConfigManager = serverConfigManager;
|
||||||
_lightlessProfileManager = lightlessProfileManager;
|
_lightlessProfileManager = lightlessProfileManager;
|
||||||
_performanceCollectorService = performanceCollectorService;
|
_performanceCollectorService = performanceCollectorService;
|
||||||
_fileDialogManager = fileDialogManager;
|
|
||||||
_profileTagService = profileTagService;
|
_profileTagService = profileTagService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,8 +56,7 @@ public class UiFactory
|
|||||||
_pairUiService,
|
_pairUiService,
|
||||||
dto,
|
dto,
|
||||||
_performanceCollectorService,
|
_performanceCollectorService,
|
||||||
_lightlessProfileManager,
|
_lightlessProfileManager);
|
||||||
_fileDialogManager);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public StandaloneProfileUi CreateStandaloneProfileUi(Pair pair)
|
public StandaloneProfileUi CreateStandaloneProfileUi(Pair pair)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using Dalamud.Bindings.ImGui;
|
|||||||
using Dalamud.Interface;
|
using Dalamud.Interface;
|
||||||
using Dalamud.Interface.Colors;
|
using Dalamud.Interface.Colors;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
|
using Dalamud.Utility;
|
||||||
using LightlessSync.API.Dto.Group;
|
using LightlessSync.API.Dto.Group;
|
||||||
using LightlessSync.LightlessConfiguration;
|
using LightlessSync.LightlessConfiguration;
|
||||||
using LightlessSync.Services;
|
using LightlessSync.Services;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ namespace LightlessSync.UI;
|
|||||||
|
|
||||||
public class DrawEntityFactory
|
public class DrawEntityFactory
|
||||||
{
|
{
|
||||||
|
private readonly ILogger<DrawEntityFactory> _logger;
|
||||||
private readonly ApiController _apiController;
|
private readonly ApiController _apiController;
|
||||||
private readonly LightlessMediator _mediator;
|
private readonly LightlessMediator _mediator;
|
||||||
private readonly SelectPairForTagUi _selectPairForTagUi;
|
private readonly SelectPairForTagUi _selectPairForTagUi;
|
||||||
@@ -32,6 +33,8 @@ public class DrawEntityFactory
|
|||||||
private readonly SelectTagForPairUi _selectTagForPairUi;
|
private readonly SelectTagForPairUi _selectTagForPairUi;
|
||||||
private readonly RenamePairTagUi _renamePairTagUi;
|
private readonly RenamePairTagUi _renamePairTagUi;
|
||||||
private readonly SelectTagForSyncshellUi _selectTagForSyncshellUi;
|
private readonly SelectTagForSyncshellUi _selectTagForSyncshellUi;
|
||||||
|
private readonly RenameSyncshellTagUi _renameSyncshellTagUi;
|
||||||
|
private readonly SelectSyncshellForTagUi _selectSyncshellForTagUi;
|
||||||
private readonly TagHandler _tagHandler;
|
private readonly TagHandler _tagHandler;
|
||||||
private readonly IdDisplayHandler _uidDisplayHandler;
|
private readonly IdDisplayHandler _uidDisplayHandler;
|
||||||
private readonly PairLedger _pairLedger;
|
private readonly PairLedger _pairLedger;
|
||||||
@@ -57,6 +60,7 @@ public class DrawEntityFactory
|
|||||||
PairLedger pairLedger,
|
PairLedger pairLedger,
|
||||||
PairFactory pairFactory)
|
PairFactory pairFactory)
|
||||||
{
|
{
|
||||||
|
_logger = logger;
|
||||||
_apiController = apiController;
|
_apiController = apiController;
|
||||||
_uidDisplayHandler = uidDisplayHandler;
|
_uidDisplayHandler = uidDisplayHandler;
|
||||||
_selectTagForPairUi = selectTagForPairUi;
|
_selectTagForPairUi = selectTagForPairUi;
|
||||||
|
|||||||
@@ -2721,7 +2721,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
|||||||
|
|
||||||
ImGui.Dummy(new Vector2(5));
|
ImGui.Dummy(new Vector2(5));
|
||||||
|
|
||||||
_uiShared.ColoredSeparator(UIColors.Get("DimRed"), 3f);
|
UiSharedService.ColoredSeparator(UIColors.Get("DimRed"), 3f);
|
||||||
var onlyUncompressed = textureConfig.OnlyDownscaleUncompressedTextures;
|
var onlyUncompressed = textureConfig.OnlyDownscaleUncompressedTextures;
|
||||||
if (ImGui.Checkbox("Only downscale uncompressed textures", ref onlyUncompressed))
|
if (ImGui.Checkbox("Only downscale uncompressed textures", ref onlyUncompressed))
|
||||||
{
|
{
|
||||||
@@ -2729,7 +2729,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
|||||||
_playerPerformanceConfigService.Save();
|
_playerPerformanceConfigService.Save();
|
||||||
}
|
}
|
||||||
_uiShared.DrawHelpText("If disabled, compressed textures will be targeted for downscaling too.");
|
_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));
|
ImGui.Dummy(new Vector2(5));
|
||||||
|
|
||||||
@@ -2737,7 +2737,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
|||||||
|
|
||||||
ImGui.Dummy(new Vector2(5));
|
ImGui.Dummy(new Vector2(5));
|
||||||
|
|
||||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessYellow"), 1.5f);
|
UiSharedService.ColoredSeparator(UIColors.Get("LightlessYellow"), 1.5f);
|
||||||
ImGui.TreePop();
|
ImGui.TreePop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
using Dalamud.Bindings.ImGui;
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface;
|
using Dalamud.Interface;
|
||||||
using Dalamud.Interface.Colors;
|
using Dalamud.Interface.Colors;
|
||||||
using Dalamud.Interface.ImGuiFileDialog;
|
|
||||||
using Dalamud.Interface.Textures.TextureWraps;
|
using Dalamud.Interface.Textures.TextureWraps;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
using LightlessSync.API.Data.Enum;
|
using LightlessSync.API.Data.Enum;
|
||||||
using LightlessSync.API.Data.Extensions;
|
using LightlessSync.API.Data.Extensions;
|
||||||
using LightlessSync.API.Dto.Group;
|
using LightlessSync.API.Dto.Group;
|
||||||
|
using LightlessSync.PlayerData.Pairs;
|
||||||
using LightlessSync.Services;
|
using LightlessSync.Services;
|
||||||
using LightlessSync.Services.Mediator;
|
using LightlessSync.Services.Mediator;
|
||||||
using LightlessSync.PlayerData.Pairs;
|
using LightlessSync.Services.Profiles;
|
||||||
|
using LightlessSync.UI.Services;
|
||||||
using LightlessSync.WebAPI;
|
using LightlessSync.WebAPI;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using SixLabors.ImageSharp;
|
using SixLabors.ImageSharp;
|
||||||
using SixLabors.ImageSharp.PixelFormats;
|
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
|
||||||
namespace LightlessSync.UI;
|
namespace LightlessSync.UI;
|
||||||
@@ -25,38 +25,29 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
|||||||
private readonly bool _isModerator = false;
|
private readonly bool _isModerator = false;
|
||||||
private readonly bool _isOwner = false;
|
private readonly bool _isOwner = false;
|
||||||
private readonly List<string> _oneTimeInvites = [];
|
private readonly List<string> _oneTimeInvites = [];
|
||||||
private readonly PairManager _pairManager;
|
|
||||||
private readonly LightlessProfileManager _lightlessProfileManager;
|
private readonly LightlessProfileManager _lightlessProfileManager;
|
||||||
private readonly FileDialogManager _fileDialogManager;
|
|
||||||
private readonly UiSharedService _uiSharedService;
|
private readonly UiSharedService _uiSharedService;
|
||||||
|
private readonly PairUiService _pairUiService;
|
||||||
private List<BannedGroupUserDto> _bannedUsers = [];
|
private List<BannedGroupUserDto> _bannedUsers = [];
|
||||||
private LightlessGroupProfileData? _profileData = null;
|
private LightlessGroupProfileData? _profileData = null;
|
||||||
private bool _adjustedForScollBarsLocalProfile = false;
|
|
||||||
private bool _adjustedForScollBarsOnlineProfile = false;
|
|
||||||
private string _descriptionText = string.Empty;
|
|
||||||
private IDalamudTextureWrap? _pfpTextureWrap;
|
private IDalamudTextureWrap? _pfpTextureWrap;
|
||||||
private string _profileDescription = string.Empty;
|
private string _profileDescription = string.Empty;
|
||||||
private byte[] _profileImage = [];
|
|
||||||
private bool _showFileDialogError = false;
|
|
||||||
private int _multiInvites;
|
private int _multiInvites;
|
||||||
private string _newPassword;
|
private string _newPassword;
|
||||||
private bool _pwChangeSuccess;
|
private bool _pwChangeSuccess;
|
||||||
private Task<int>? _pruneTestTask;
|
private Task<int>? _pruneTestTask;
|
||||||
private Task<int>? _pruneTask;
|
private Task<int>? _pruneTask;
|
||||||
private int _pruneDays = 14;
|
private int _pruneDays = 14;
|
||||||
private List<int> _selectedTags = [];
|
|
||||||
|
|
||||||
public SyncshellAdminUI(ILogger<SyncshellAdminUI> logger, LightlessMediator mediator, ApiController apiController,
|
public SyncshellAdminUI(ILogger<SyncshellAdminUI> logger, LightlessMediator mediator, ApiController apiController,
|
||||||
UiSharedService uiSharedService, PairManager pairManager, 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)
|
: base(logger, mediator, "Syncshell Admin Panel (" + groupFullInfo.GroupAliasOrGID + ")", performanceCollectorService)
|
||||||
{
|
{
|
||||||
GroupFullInfo = groupFullInfo;
|
GroupFullInfo = groupFullInfo;
|
||||||
_apiController = apiController;
|
_apiController = apiController;
|
||||||
_uiSharedService = uiSharedService;
|
_uiSharedService = uiSharedService;
|
||||||
_pairManager = pairManager;
|
|
||||||
_lightlessProfileManager = lightlessProfileManager;
|
_lightlessProfileManager = lightlessProfileManager;
|
||||||
_fileDialogManager = fileDialogManager;
|
_pairUiService = pairUiService;
|
||||||
|
|
||||||
_isOwner = string.Equals(GroupFullInfo.OwnerUID, _apiController.UID, StringComparison.Ordinal);
|
_isOwner = string.Equals(GroupFullInfo.OwnerUID, _apiController.UID, StringComparison.Ordinal);
|
||||||
_isModerator = GroupFullInfo.GroupUserInfo.IsModerator();
|
_isModerator = GroupFullInfo.GroupUserInfo.IsModerator();
|
||||||
_newPassword = string.Empty;
|
_newPassword = string.Empty;
|
||||||
@@ -76,6 +67,7 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
|||||||
MinimumSize = new(700, 500),
|
MinimumSize = new(700, 500),
|
||||||
MaximumSize = new(700, 2000),
|
MaximumSize = new(700, 2000),
|
||||||
};
|
};
|
||||||
|
_pairUiService = pairUiService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GroupFullInfoDto GroupFullInfo { get; private set; }
|
public GroupFullInfoDto GroupFullInfo { get; private set; }
|
||||||
@@ -85,10 +77,13 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
|||||||
if (!_isModerator && !_isOwner) return;
|
if (!_isModerator && !_isOwner) return;
|
||||||
|
|
||||||
_logger.LogTrace("Drawing Syncshell Admin UI for {group}", GroupFullInfo.GroupAliasOrGID);
|
_logger.LogTrace("Drawing Syncshell Admin UI for {group}", GroupFullInfo.GroupAliasOrGID);
|
||||||
GroupFullInfo = _pairManager.Groups[GroupFullInfo.Group];
|
var snapshot = _pairUiService.GetSnapshot();
|
||||||
|
if (snapshot.GroupsByGid.TryGetValue(GroupFullInfo.Group.GID, out var updatedInfo))
|
||||||
|
{
|
||||||
|
GroupFullInfo = updatedInfo;
|
||||||
|
}
|
||||||
|
|
||||||
_profileData = _lightlessProfileManager.GetLightlessGroupProfile(GroupFullInfo.Group);
|
_profileData = _lightlessProfileManager.GetLightlessGroupProfile(GroupFullInfo.Group);
|
||||||
GetTagsFromProfile();
|
|
||||||
|
|
||||||
using var id = ImRaii.PushId("syncshell_admin_" + GroupFullInfo.GID);
|
using var id = ImRaii.PushId("syncshell_admin_" + GroupFullInfo.GID);
|
||||||
using (_uiSharedService.UidFont.Push())
|
using (_uiSharedService.UidFont.Push())
|
||||||
@@ -207,189 +202,51 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
|||||||
ownerTab.Dispose();
|
ownerTab.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawProfile()
|
private void DrawProfile()
|
||||||
{
|
{
|
||||||
var profileTab = ImRaii.TabItem("Profile");
|
var profileTab = ImRaii.TabItem("Profile");
|
||||||
|
if (!profileTab)
|
||||||
|
return;
|
||||||
|
|
||||||
if (profileTab)
|
if (_profileData != null)
|
||||||
{
|
{
|
||||||
if (_uiSharedService.MediumTreeNode("Current Profile", UIColors.Get("LightlessPurple")))
|
if (!string.Equals(_profileDescription, _profileData.Description, StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
ImGui.Dummy(new Vector2(5));
|
_profileDescription = _profileData.Description;
|
||||||
|
|
||||||
if (_profileData == null)
|
|
||||||
{
|
|
||||||
UiSharedService.ColorTextWrapped("Failed to load profile data.", ImGuiColors.DalamudRed);
|
|
||||||
ImGui.TreePop();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_profileImage.SequenceEqual(_profileData.ProfileImageData.Value))
|
|
||||||
{
|
|
||||||
_profileImage = _profileData.ProfileImageData.Value;
|
|
||||||
_pfpTextureWrap?.Dispose();
|
|
||||||
_pfpTextureWrap = _uiSharedService.LoadImage(_profileImage);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.Equals(_profileDescription, _profileData.Description, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
_profileDescription = _profileData.Description;
|
|
||||||
_descriptionText = _profileDescription;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_pfpTextureWrap != null)
|
|
||||||
{
|
|
||||||
ImGui.Image(_pfpTextureWrap.Handle, ImGuiHelpers.ScaledVector2(_pfpTextureWrap.Width, _pfpTextureWrap.Height));
|
|
||||||
}
|
|
||||||
|
|
||||||
var spacing = ImGui.GetStyle().ItemSpacing.X;
|
|
||||||
ImGuiHelpers.ScaledRelativeSameLine(256, spacing);
|
|
||||||
using (_uiSharedService.GameFont.Push())
|
|
||||||
{
|
|
||||||
var descriptionTextSize = ImGui.CalcTextSize(_profileData.Description, wrapWidth: 256f);
|
|
||||||
var childFrame = ImGuiHelpers.ScaledVector2(256 + ImGui.GetStyle().WindowPadding.X + ImGui.GetStyle().WindowBorderSize, 256);
|
|
||||||
if (descriptionTextSize.Y > childFrame.Y)
|
|
||||||
{
|
|
||||||
_adjustedForScollBarsOnlineProfile = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_adjustedForScollBarsOnlineProfile = false;
|
|
||||||
}
|
|
||||||
childFrame = childFrame with
|
|
||||||
{
|
|
||||||
X = childFrame.X + (_adjustedForScollBarsOnlineProfile ? ImGui.GetStyle().ScrollbarSize : 0),
|
|
||||||
};
|
|
||||||
if (ImGui.BeginChildFrame(101, childFrame))
|
|
||||||
{
|
|
||||||
UiSharedService.TextWrapped(_profileData.Description);
|
|
||||||
}
|
|
||||||
ImGui.EndChildFrame();
|
|
||||||
ImGui.TreePop();
|
|
||||||
}
|
|
||||||
var nsfw = _profileData.IsNsfw;
|
|
||||||
ImGui.BeginDisabled();
|
|
||||||
ImGui.Checkbox("Is NSFW", ref nsfw);
|
|
||||||
ImGui.EndDisabled();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.Separator();
|
UiSharedService.TextWrapped("Preview the Syncshell profile in a standalone window.");
|
||||||
|
|
||||||
if (_uiSharedService.MediumTreeNode("Profile Settings", UIColors.Get("LightlessPurple")))
|
if (_uiSharedService.IconTextButton(FontAwesomeIcon.AddressCard, "Open Syncshell Profile"))
|
||||||
{
|
{
|
||||||
ImGui.Dummy(new Vector2(5));
|
Mediator.Publish(new GroupProfileOpenStandaloneMessage(GroupFullInfo));
|
||||||
ImGui.TextUnformatted($"Profile Picture:");
|
|
||||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.FileUpload, "Upload new profile picture"))
|
|
||||||
{
|
|
||||||
_fileDialogManager.OpenFileDialog("Select new Profile picture", ".png", (success, file) =>
|
|
||||||
{
|
|
||||||
if (!success) return;
|
|
||||||
_ = Task.Run(async () =>
|
|
||||||
{
|
|
||||||
var fileContent = await File.ReadAllBytesAsync(file).ConfigureAwait(false);
|
|
||||||
MemoryStream ms = new(fileContent);
|
|
||||||
await using (ms.ConfigureAwait(false))
|
|
||||||
{
|
|
||||||
var format = await Image.DetectFormatAsync(ms).ConfigureAwait(false);
|
|
||||||
if (!format.FileExtensions.Contains("png", StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
_showFileDialogError = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
using var image = Image.Load<Rgba32>(fileContent);
|
|
||||||
|
|
||||||
if (image.Width > 512 || image.Height > 512 || (fileContent.Length > 2000 * 1024))
|
|
||||||
{
|
|
||||||
_showFileDialogError = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_showFileDialogError = false;
|
|
||||||
await _apiController.GroupSetProfile(new GroupProfileDto(new GroupData(GroupFullInfo.Group.AliasOrGID), Description: null, Tags: null, Convert.ToBase64String(fileContent), BannerBase64: null, IsNsfw: null, IsDisabled: null))
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
UiSharedService.AttachToolTip("Select and upload a new profile picture");
|
|
||||||
ImGui.SameLine();
|
|
||||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Trash, "Clear uploaded profile picture"))
|
|
||||||
{
|
|
||||||
_ = _apiController.GroupSetProfile(new GroupProfileDto(new GroupData(GroupFullInfo.Group.AliasOrGID), Description: null, Tags: null, PictureBase64: null, BannerBase64: null, IsNsfw: null, IsDisabled: null));
|
|
||||||
}
|
|
||||||
UiSharedService.AttachToolTip("Clear your currently uploaded profile picture");
|
|
||||||
if (_showFileDialogError)
|
|
||||||
{
|
|
||||||
UiSharedService.ColorTextWrapped("The profile picture must be a PNG file with a maximum height and width of 256px and 250KiB size", ImGuiColors.DalamudRed);
|
|
||||||
}
|
|
||||||
ImGui.Separator();
|
|
||||||
ImGui.TextUnformatted($"Tags:");
|
|
||||||
var childFrameLocal = ImGuiHelpers.ScaledVector2(256 + ImGui.GetStyle().WindowPadding.X + ImGui.GetStyle().WindowBorderSize, 200);
|
|
||||||
|
|
||||||
var allCategoryIndexes = Enum.GetValues<ProfileTags>()
|
|
||||||
.Cast<int>()
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
foreach (int tag in allCategoryIndexes)
|
|
||||||
{
|
|
||||||
using (ImRaii.PushId($"tag-{tag}")) DrawTag(tag);
|
|
||||||
}
|
|
||||||
ImGui.Separator();
|
|
||||||
var widthTextBox = 400;
|
|
||||||
var posX = ImGui.GetCursorPosX();
|
|
||||||
ImGui.TextUnformatted($"Description {_descriptionText.Length}/1500");
|
|
||||||
ImGui.SetCursorPosX(posX);
|
|
||||||
ImGuiHelpers.ScaledRelativeSameLine(widthTextBox, ImGui.GetStyle().ItemSpacing.X);
|
|
||||||
ImGui.TextUnformatted("Preview (approximate)");
|
|
||||||
using (_uiSharedService.GameFont.Push())
|
|
||||||
ImGui.InputTextMultiline("##description", ref _descriptionText, 1500, ImGuiHelpers.ScaledVector2(widthTextBox, 200));
|
|
||||||
|
|
||||||
ImGui.SameLine();
|
|
||||||
|
|
||||||
using (_uiSharedService.GameFont.Push())
|
|
||||||
{
|
|
||||||
var descriptionTextSizeLocal = ImGui.CalcTextSize(_descriptionText, wrapWidth: 256f);
|
|
||||||
if (descriptionTextSizeLocal.Y > childFrameLocal.Y)
|
|
||||||
{
|
|
||||||
_adjustedForScollBarsLocalProfile = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_adjustedForScollBarsLocalProfile = false;
|
|
||||||
}
|
|
||||||
childFrameLocal = childFrameLocal with
|
|
||||||
{
|
|
||||||
X = childFrameLocal.X + (_adjustedForScollBarsLocalProfile ? ImGui.GetStyle().ScrollbarSize : 0),
|
|
||||||
};
|
|
||||||
if (ImGui.BeginChildFrame(102, childFrameLocal))
|
|
||||||
{
|
|
||||||
UiSharedService.TextWrapped(_descriptionText);
|
|
||||||
}
|
|
||||||
ImGui.EndChildFrame();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Save, "Save Description"))
|
|
||||||
{
|
|
||||||
_ = _apiController.GroupSetProfile(new GroupProfileDto(new GroupData(GroupFullInfo.Group.AliasOrGID), Description: _descriptionText, Tags: null, PictureBase64: null, BannerBase64: null, IsNsfw: null, IsDisabled: null));
|
|
||||||
}
|
|
||||||
UiSharedService.AttachToolTip("Sets your profile description text");
|
|
||||||
ImGui.SameLine();
|
|
||||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Trash, "Clear Description"))
|
|
||||||
{
|
|
||||||
_ = _apiController.GroupSetProfile(new GroupProfileDto(new GroupData(GroupFullInfo.Group.AliasOrGID), Description: null, Tags: null, PictureBase64: null, BannerBase64: null, IsNsfw: null, IsDisabled: null));
|
|
||||||
}
|
|
||||||
UiSharedService.AttachToolTip("Clears your profile description text");
|
|
||||||
ImGui.Separator();
|
|
||||||
ImGui.TextUnformatted($"Profile Options:");
|
|
||||||
var isNsfw = _profileData?.IsNsfw ?? false;
|
|
||||||
if (ImGui.Checkbox("Profile is NSFW", ref isNsfw))
|
|
||||||
{
|
|
||||||
_ = _apiController.GroupSetProfile(new GroupProfileDto(new GroupData(GroupFullInfo.Group.AliasOrGID), Description: null, Tags: null, PictureBase64: null, BannerBase64: null, IsNsfw: isNsfw, IsDisabled: null));
|
|
||||||
}
|
|
||||||
_uiSharedService.DrawHelpText("If your profile description or image can be considered NSFW, toggle this to ON");
|
|
||||||
ImGui.TreePop();
|
|
||||||
}
|
}
|
||||||
|
UiSharedService.AttachToolTip("Opens the standalone Syncshell profile window for this group.");
|
||||||
|
|
||||||
|
ImGuiHelpers.ScaledDummy(2f);
|
||||||
|
ImGui.TextDisabled("Profile Flags");
|
||||||
|
ImGui.BulletText(_profileData.IsNsfw ? "Marked as NSFW" : "Marked as SFW");
|
||||||
|
ImGui.BulletText(_profileData.IsDisabled ? "Profile disabled for viewers" : "Profile active");
|
||||||
|
|
||||||
|
ImGuiHelpers.ScaledDummy(2f);
|
||||||
|
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.");
|
||||||
|
ImGuiHelpers.ScaledDummy(2f);
|
||||||
|
|
||||||
|
if (_uiSharedService.IconTextButton(FontAwesomeIcon.UserEdit, "Open Syncshell Profile Editor"))
|
||||||
|
{
|
||||||
|
Mediator.Publish(new OpenGroupProfileEditorMessage(GroupFullInfo));
|
||||||
|
}
|
||||||
|
UiSharedService.AttachToolTip("Launches the editor window and associated live preview for this syncshell.");
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UiSharedService.TextWrapped("Profile information is loading...");
|
||||||
|
}
|
||||||
|
|
||||||
profileTab.Dispose();
|
profileTab.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -400,7 +257,8 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
|||||||
{
|
{
|
||||||
if (_uiSharedService.MediumTreeNode("User List & Administration", UIColors.Get("LightlessPurple")))
|
if (_uiSharedService.MediumTreeNode("User List & Administration", UIColors.Get("LightlessPurple")))
|
||||||
{
|
{
|
||||||
if (!_pairManager.GroupPairs.TryGetValue(GroupFullInfo, out var pairs))
|
var snapshot = _pairUiService.GetSnapshot();
|
||||||
|
if (!snapshot.GroupPairs.TryGetValue(GroupFullInfo, out var pairs))
|
||||||
{
|
{
|
||||||
UiSharedService.ColorTextWrapped("No users found in this Syncshell", ImGuiColors.DalamudYellow);
|
UiSharedService.ColorTextWrapped("No users found in this Syncshell", ImGuiColors.DalamudYellow);
|
||||||
}
|
}
|
||||||
@@ -736,33 +594,6 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
|||||||
}
|
}
|
||||||
inviteTab.Dispose();
|
inviteTab.Dispose();
|
||||||
}
|
}
|
||||||
private void DrawTag(int tag)
|
|
||||||
{
|
|
||||||
var HasTag = _selectedTags.Contains(tag);
|
|
||||||
var tagName = (ProfileTags)tag;
|
|
||||||
|
|
||||||
if (ImGui.Checkbox(tagName.ToString(), ref HasTag))
|
|
||||||
{
|
|
||||||
if (HasTag)
|
|
||||||
{
|
|
||||||
_selectedTags.Add(tag);
|
|
||||||
_ = _apiController.GroupSetProfile(new GroupProfileDto(new GroupData(GroupFullInfo.Group.AliasOrGID), Description: null, Tags: _selectedTags.ToArray(), PictureBase64: null, BannerBase64: null, IsNsfw: null, IsDisabled: null));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_selectedTags.Remove(tag);
|
|
||||||
_ = _apiController.GroupSetProfile(new GroupProfileDto(new GroupData(GroupFullInfo.Group.AliasOrGID), Description: null, Tags: _selectedTags.ToArray(), PictureBase64: null, BannerBase64: null, IsNsfw: null, IsDisabled: null));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GetTagsFromProfile()
|
|
||||||
{
|
|
||||||
if (_profileData != null)
|
|
||||||
{
|
|
||||||
_selectedTags = [.. _profileData.Tags];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnClose()
|
public override void OnClose()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -474,7 +474,8 @@ public class SyncshellFinderUI : WindowMediatorSubscriberBase
|
|||||||
private async Task RefreshSyncshellsAsync(string? gid = null)
|
private async Task RefreshSyncshellsAsync(string? gid = null)
|
||||||
{
|
{
|
||||||
var syncshellBroadcasts = _broadcastScannerService.GetActiveSyncshellBroadcasts();
|
var syncshellBroadcasts = _broadcastScannerService.GetActiveSyncshellBroadcasts();
|
||||||
_currentSyncshells = [.. _pairManager.GroupPairs.Select(g => g.Key)];
|
var snapshot = _pairUiService.GetSnapshot();
|
||||||
|
_currentSyncshells = [.. snapshot.GroupPairs.Keys];
|
||||||
|
|
||||||
_recentlyJoined.RemoveWhere(gid =>
|
_recentlyJoined.RemoveWhere(gid =>
|
||||||
_currentSyncshells.Exists(s => string.Equals(s.GID, gid, StringComparison.Ordinal)));
|
_currentSyncshells.Exists(s => string.Equals(s.GID, gid, StringComparison.Ordinal)));
|
||||||
|
|||||||
@@ -506,7 +506,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
|
|||||||
ImGui.Dummy(new Vector2(0, thickness * ImGuiHelpers.GlobalScale));
|
ImGui.Dummy(new Vector2(0, thickness * ImGuiHelpers.GlobalScale));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RoundedSeparator(Vector4? color = null, float thickness = 2f, float indent = 0f, float rounding = 4f)
|
public void RoundedSeparator(Vector4? color = null, float thickness = 2f, float indent = 0f, float rounding = 4f)
|
||||||
{
|
{
|
||||||
float scale = ImGuiHelpers.GlobalScale;
|
float scale = ImGuiHelpers.GlobalScale;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user