using Dalamud.Interface; using Dalamud.Interface.ImGuiFileDialog; using Dalamud.Interface.Windowing; using LightlessSync.LightlessConfiguration; using LightlessSync.PlayerData.Factories; using LightlessSync.Services.Mediator; using LightlessSync.UI; using LightlessSync.UI.Style; using Microsoft.Extensions.Logging; namespace LightlessSync.Services; public sealed class UiService : DisposableMediatorSubscriberBase { private readonly List _createdWindows = []; private readonly List _registeredWindows = []; private readonly HashSet _uiHiddenWindows = []; private readonly IUiBuilder _uiBuilder; private readonly FileDialogManager _fileDialogManager; private readonly ILogger _logger; private readonly LightlessConfigService _lightlessConfigService; private readonly DalamudUtilService _dalamudUtilService; private readonly WindowSystem _windowSystem; private readonly UiFactory _uiFactory; private readonly PairFactory _pairFactory; private bool _uiHideActive; public UiService(ILogger logger, IUiBuilder uiBuilder, LightlessConfigService lightlessConfigService, DalamudUtilService dalamudUtilService, WindowSystem windowSystem, IEnumerable windows, UiFactory uiFactory, FileDialogManager fileDialogManager, LightlessMediator lightlessMediator, PairFactory pairFactory) : base(logger, lightlessMediator) { _logger = logger; _logger.LogTrace("Creating {type}", GetType().Name); _uiBuilder = uiBuilder; _lightlessConfigService = lightlessConfigService; _dalamudUtilService = dalamudUtilService; _windowSystem = windowSystem; _uiFactory = uiFactory; _pairFactory = pairFactory; _fileDialogManager = fileDialogManager; _uiBuilder.DisableGposeUiHide = true; _uiBuilder.Draw += Draw; _uiBuilder.OpenConfigUi += ToggleUi; _uiBuilder.OpenMainUi += ToggleMainUi; foreach (var window in windows) { _registeredWindows.Add(window); _windowSystem.AddWindow(window); } Mediator.Subscribe(this, (msg) => { var resolvedPair = _pairFactory.Create(msg.Pair.UniqueIdent) ?? msg.Pair; if (!_createdWindows.Exists(p => p is StandaloneProfileUi ui && ui.Pair != null && ui.Pair.UniqueIdent == resolvedPair.UniqueIdent)) { var window = _uiFactory.CreateStandaloneProfileUi(resolvedPair); _createdWindows.Add(window); _windowSystem.AddWindow(window); } }); Mediator.Subscribe(this, msg => { var existingWindow = _createdWindows.Find(p => p is StandaloneProfileUi ui && ui.IsGroupProfile && ui.ProfileGroupData is not null && string.Equals(ui.ProfileGroupData.GID, msg.Group.GID, StringComparison.Ordinal)); if (existingWindow is StandaloneProfileUi existing) { existing.IsOpen = true; } else { var window = _uiFactory.CreateStandaloneGroupProfileUi(msg.Group); _createdWindows.Add(window); _windowSystem.AddWindow(window); } }); Mediator.Subscribe(this, msg => { var window = _createdWindows.Find(p => p is StandaloneProfileUi ui && ui.IsGroupProfile && ui.ProfileGroupData is not null && string.Equals(ui.ProfileGroupData.GID, msg.Group.Group.GID, StringComparison.Ordinal)); if (window is not null) { _windowSystem.RemoveWindow(window); _createdWindows.Remove(window); window.Dispose(); } }); Mediator.Subscribe(this, msg => { if (!_createdWindows.Exists(p => p is StandaloneProfileUi ui && ui.Pair is null && !ui.IsGroupProfile && !ui.IsLightfinderContext && string.Equals(ui.ProfileUserData.UID, msg.User.UID, StringComparison.Ordinal))) { var window = _uiFactory.CreateStandaloneProfileUi(msg.User); _createdWindows.Add(window); _windowSystem.AddWindow(window); } }); Mediator.Subscribe(this, msg => { var window = _createdWindows.Find(p => p is StandaloneProfileUi ui && ui.Pair is null && !ui.IsGroupProfile && !ui.IsLightfinderContext && string.Equals(ui.ProfileUserData.UID, msg.User.UID, StringComparison.Ordinal)); if (window is not null) { _windowSystem.RemoveWindow(window); _createdWindows.Remove(window); window.Dispose(); } }); Mediator.Subscribe(this, msg => { if (!_createdWindows.Exists(p => p is StandaloneProfileUi ui && ui.IsLightfinderContext && string.Equals(ui.LightfinderCid, msg.HashedCid, StringComparison.Ordinal))) { var window = _uiFactory.CreateLightfinderProfileUi(msg.User, msg.HashedCid); _createdWindows.Add(window); _windowSystem.AddWindow(window); } }); Mediator.Subscribe(this, msg => { if (!_createdWindows.Exists(p => p is StandaloneProfileUi ui && !ui.IsLightfinderContext && !ui.IsGroupProfile && ui.Pair is null && ui.ProfileUserData is not null && string.Equals(ui.ProfileUserData.UID, msg.User.UID, StringComparison.Ordinal))) { var window = _uiFactory.CreateStandaloneProfileUi(msg.User); _createdWindows.Add(window); _windowSystem.AddWindow(window); } }); Mediator.Subscribe(this, (msg) => { if (!_createdWindows.Exists(p => p is SyncshellAdminUI ui && string.Equals(ui.GroupFullInfo.GID, msg.GroupInfo.GID, StringComparison.Ordinal))) { var window = _uiFactory.CreateSyncshellAdminUi(msg.GroupInfo); _createdWindows.Add(window); _windowSystem.AddWindow(window); } }); Mediator.Subscribe(this, (msg) => { var resolvedPair = _pairFactory.Create(msg.Pair.UniqueIdent) ?? msg.Pair; if (!_createdWindows.Exists(p => p is PermissionWindowUI ui && ui.Pair is not null && ui.Pair.UniqueIdent == resolvedPair.UniqueIdent)) { var window = _uiFactory.CreatePermissionPopupUi(resolvedPair); _createdWindows.Add(window); _windowSystem.AddWindow(window); } }); Mediator.Subscribe(this, (msg) => { _windowSystem.RemoveWindow(msg.Window); _createdWindows.Remove(msg.Window); _registeredWindows.Remove(msg.Window); _uiHiddenWindows.Remove(msg.Window); msg.Window.Dispose(); }); } public void ToggleMainUi() { if (_lightlessConfigService.Current.HasValidSetup()) Mediator.Publish(new UiToggleMessage(typeof(CompactUi))); else Mediator.Publish(new UiToggleMessage(typeof(IntroUi))); } public void ToggleUi() { if (_lightlessConfigService.Current.HasValidSetup()) Mediator.Publish(new UiToggleMessage(typeof(SettingsUi))); else Mediator.Publish(new UiToggleMessage(typeof(IntroUi))); } protected override void Dispose(bool disposing) { base.Dispose(disposing); _logger.LogTrace("Disposing {type}", GetType().Name); _windowSystem.RemoveAllWindows(); foreach (var window in _createdWindows) { window.Dispose(); } _uiBuilder.Draw -= Draw; _uiBuilder.OpenConfigUi -= ToggleUi; _uiBuilder.OpenMainUi -= ToggleMainUi; } private void Draw() { MainStyle.PushStyle(); try { var hideOtherUi = ShouldHideOtherUi(); UpdateUiHideState(hideOtherUi); _windowSystem.Draw(); if (!hideOtherUi) _fileDialogManager.Draw(); } finally { MainStyle.PopStyle(); } } private bool ShouldHideOtherUi() { var config = _lightlessConfigService.Current; if (!config.ShowUiWhenUiHidden && _dalamudUtilService.IsGameUiHidden) return true; if (!config.ShowUiInGpose && _dalamudUtilService.IsInGpose) return true; return false; } private void UpdateUiHideState(bool hideOtherUi) { if (!hideOtherUi) { if (_uiHideActive) { foreach (var window in _uiHiddenWindows) { window.IsOpen = true; } _uiHiddenWindows.Clear(); _uiHideActive = false; } return; } _uiHideActive = true; foreach (var window in EnumerateManagedWindows()) { if (window is ZoneChatUi) continue; if (!window.IsOpen) continue; _uiHiddenWindows.Add(window); window.IsOpen = false; } } private IEnumerable EnumerateManagedWindows() { foreach (var window in _registeredWindows) { yield return window; } foreach (var window in _createdWindows) { yield return window; } } }