299 lines
11 KiB
C#
299 lines
11 KiB
C#
using Dalamud.Bindings.ImGui;
|
|
using Dalamud.Interface;
|
|
using Dalamud.Interface.Colors;
|
|
using Dalamud.Interface.Utility;
|
|
using Dalamud.Interface.Utility.Raii;
|
|
using LightlessSync.API.Data.Enum;
|
|
using LightlessSync.API.Dto;
|
|
using LightlessSync.API.Dto.Group;
|
|
using LightlessSync.LightlessConfiguration;
|
|
using LightlessSync.Services;
|
|
using LightlessSync.Services.Mediator;
|
|
using LightlessSync.Utils;
|
|
using LightlessSync.WebAPI;
|
|
using Microsoft.Extensions.Logging;
|
|
using LightlessSync.API.Data.Extensions;
|
|
using System.Numerics;
|
|
|
|
namespace LightlessSync.UI;
|
|
|
|
public class SyncshellFinderUI : WindowMediatorSubscriberBase
|
|
{
|
|
private readonly ApiController _apiController;
|
|
private readonly LightlessConfigService _configService;
|
|
private readonly BroadcastService _broadcastService;
|
|
private readonly UiSharedService _uiSharedService;
|
|
private readonly BroadcastScannerService _broadcastScannerService;
|
|
|
|
private readonly List<GroupJoinDto> _nearbySyncshells = new();
|
|
private int _selectedNearbyIndex = -1;
|
|
|
|
private GroupJoinDto? _joinDto;
|
|
private GroupJoinInfoDto? _joinInfo;
|
|
private DefaultPermissionsDto _ownPermissions = null!;
|
|
|
|
public SyncshellFinderUI(
|
|
ILogger<SyncshellFinderUI> logger,
|
|
LightlessMediator mediator,
|
|
PerformanceCollectorService performanceCollectorService,
|
|
BroadcastService broadcastService,
|
|
LightlessConfigService configService,
|
|
UiSharedService uiShared,
|
|
ApiController apiController,
|
|
BroadcastScannerService broadcastScannerService
|
|
) : base(logger, mediator, "Shellfinder###LightlessSyncshellFinderUI", performanceCollectorService)
|
|
{
|
|
_broadcastService = broadcastService;
|
|
_uiSharedService = uiShared;
|
|
_configService = configService;
|
|
_apiController = apiController;
|
|
_broadcastScannerService = broadcastScannerService;
|
|
|
|
IsOpen = false;
|
|
SizeConstraints = new()
|
|
{
|
|
MinimumSize = new(600, 400),
|
|
MaximumSize = new(600, 550)
|
|
};
|
|
|
|
Mediator.Subscribe<SyncshellBroadcastsUpdatedMessage>(this, async _ => await RefreshSyncshellsAsync());
|
|
Mediator.Subscribe<BroadcastStatusChangedMessage>(this, async _ => await RefreshSyncshellsAsync());
|
|
}
|
|
|
|
public override async void OnOpen()
|
|
{
|
|
_ownPermissions = _apiController.DefaultPermissions.DeepClone()!;
|
|
await RefreshSyncshellsAsync();
|
|
}
|
|
|
|
protected override void DrawInternal()
|
|
{
|
|
_uiSharedService.MediumText("Nearby Syncshells", UIColors.Get("PairBlue"));
|
|
_uiSharedService.ColoredSeparator(UIColors.Get("PairBlue"));
|
|
|
|
if (_nearbySyncshells.Count == 0)
|
|
{
|
|
ImGui.TextColored(ImGuiColors.DalamudGrey, "No nearby syncshells are being broadcasted.");
|
|
|
|
if (!_broadcastService.IsBroadcasting)
|
|
{
|
|
|
|
_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("LightlessYellow2"));
|
|
|
|
if (ImGui.Button("Open Lightfinder", new Vector2(200 * ImGuiHelpers.GlobalScale, 0)))
|
|
{
|
|
Mediator.Publish(new UiToggleMessage(typeof(BroadcastUI)));
|
|
}
|
|
|
|
ImGui.PopStyleColor();
|
|
ImGui.PopStyleVar();
|
|
|
|
return;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (ImGui.BeginTable("##NearbySyncshellsTable", 3, ImGuiTableFlags.Borders | ImGuiTableFlags.RowBg))
|
|
{
|
|
ImGui.TableSetupColumn("Alias", ImGuiTableColumnFlags.WidthStretch);
|
|
ImGui.TableSetupColumn("GID", ImGuiTableColumnFlags.WidthStretch);
|
|
ImGui.TableSetupColumn("Join", ImGuiTableColumnFlags.WidthFixed, 80f * ImGuiHelpers.GlobalScale);
|
|
ImGui.TableHeadersRow();
|
|
|
|
for (int i = 0; i < _nearbySyncshells.Count; i++)
|
|
{
|
|
var shell = _nearbySyncshells[i];
|
|
|
|
ImGui.TableNextRow();
|
|
ImGui.TableNextColumn();
|
|
ImGui.TextUnformatted(shell.Group.Alias ?? "(No Alias)");
|
|
ImGui.TableNextColumn();
|
|
ImGui.TextUnformatted(shell.Group.GID);
|
|
ImGui.TableNextColumn();
|
|
|
|
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));
|
|
|
|
if (ImGui.Button(label))
|
|
{
|
|
_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}");
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
ImGui.PopStyleColor(3);
|
|
}
|
|
|
|
ImGui.EndTable();
|
|
}
|
|
|
|
if (_joinDto != null && _joinInfo != null && _joinInfo.Success)
|
|
DrawConfirmation();
|
|
}
|
|
|
|
private void DrawConfirmation()
|
|
{
|
|
ImGui.Separator();
|
|
ImGui.TextUnformatted($"Join Syncshell: {_joinDto.Group.AliasOrGID} by {_joinInfo.OwnerAliasOrUID}");
|
|
ImGuiHelpers.ScaledDummy(2f);
|
|
ImGui.TextUnformatted("Suggested Syncshell Permissions:");
|
|
|
|
DrawPermissionRow("Sounds", _joinInfo.GroupPermissions.IsPreferDisableSounds(), _ownPermissions.DisableGroupSounds, v => _ownPermissions.DisableGroupSounds = v);
|
|
DrawPermissionRow("Animations", _joinInfo.GroupPermissions.IsPreferDisableAnimations(), _ownPermissions.DisableGroupAnimations, v => _ownPermissions.DisableGroupAnimations = v);
|
|
DrawPermissionRow("VFX", _joinInfo.GroupPermissions.IsPreferDisableVFX(), _ownPermissions.DisableGroupVFX, v => _ownPermissions.DisableGroupVFX = v);
|
|
|
|
ImGui.NewLine();
|
|
ImGui.NewLine();
|
|
|
|
if (_uiSharedService.IconTextButton(Dalamud.Interface.FontAwesomeIcon.Plus, $"Finalize and join {_joinDto.Group.AliasOrGID}"))
|
|
{
|
|
var finalPermissions = GroupUserPreferredPermissions.NoneSet;
|
|
finalPermissions.SetDisableSounds(_ownPermissions.DisableGroupSounds);
|
|
finalPermissions.SetDisableAnimations(_ownPermissions.DisableGroupAnimations);
|
|
finalPermissions.SetDisableVFX(_ownPermissions.DisableGroupVFX);
|
|
|
|
_ = _apiController.GroupJoinFinalize(new GroupJoinDto(_joinDto.Group, _joinDto.Password, finalPermissions, true));
|
|
_joinDto = null;
|
|
_joinInfo = null;
|
|
}
|
|
}
|
|
|
|
private void DrawPermissionRow(string label, bool suggested, bool current, Action<bool> apply)
|
|
{
|
|
ImGui.AlignTextToFramePadding();
|
|
ImGui.TextUnformatted($"- {label}");
|
|
|
|
ImGui.SameLine(150 * ImGuiHelpers.GlobalScale);
|
|
ImGui.TextUnformatted("Current:");
|
|
ImGui.SameLine();
|
|
_uiSharedService.BooleanToColoredIcon(!current);
|
|
|
|
ImGui.SameLine(300 * ImGuiHelpers.GlobalScale);
|
|
ImGui.TextUnformatted("Suggested:");
|
|
ImGui.SameLine();
|
|
_uiSharedService.BooleanToColoredIcon(!suggested);
|
|
|
|
ImGui.SameLine(450 * ImGuiHelpers.GlobalScale);
|
|
using var id = ImRaii.PushId(label);
|
|
if (current != suggested)
|
|
{
|
|
if (_uiSharedService.IconTextButton(FontAwesomeIcon.ArrowRight, "Apply"))
|
|
apply(suggested);
|
|
}
|
|
|
|
ImGui.NewLine();
|
|
}
|
|
|
|
private async Task RefreshSyncshellsAsync()
|
|
{
|
|
var syncshellBroadcasts = _broadcastScannerService.GetActiveSyncshellBroadcasts();
|
|
|
|
if (syncshellBroadcasts.Count == 0)
|
|
{
|
|
ClearSyncshells();
|
|
return;
|
|
}
|
|
|
|
List<GroupJoinDto> updatedList;
|
|
try
|
|
{
|
|
var groups = await _apiController.GetBroadcastedGroups(syncshellBroadcasts);
|
|
updatedList = groups?.ToList() ?? new();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Failed to refresh broadcasted syncshells.");
|
|
return;
|
|
}
|
|
|
|
var currentGids = _nearbySyncshells.Select(s => s.Group.GID).ToHashSet();
|
|
var newGids = updatedList.Select(s => s.Group.GID).ToHashSet();
|
|
|
|
if (currentGids.SetEquals(newGids))
|
|
return;
|
|
|
|
var previousGid = GetSelectedGid();
|
|
|
|
_nearbySyncshells.Clear();
|
|
_nearbySyncshells.AddRange(updatedList);
|
|
|
|
if (previousGid != null)
|
|
{
|
|
var newIndex = _nearbySyncshells.FindIndex(s => s.Group.GID == previousGid);
|
|
if (newIndex >= 0)
|
|
{
|
|
_selectedNearbyIndex = newIndex;
|
|
return;
|
|
}
|
|
}
|
|
|
|
ClearSelection();
|
|
}
|
|
|
|
private void ClearSyncshells()
|
|
{
|
|
if (_nearbySyncshells.Count == 0)
|
|
return;
|
|
|
|
_nearbySyncshells.Clear();
|
|
ClearSelection();
|
|
}
|
|
|
|
private void ClearSelection()
|
|
{
|
|
_selectedNearbyIndex = -1;
|
|
_joinDto = null;
|
|
_joinInfo = null;
|
|
}
|
|
|
|
private string? GetSelectedGid()
|
|
{
|
|
if (_selectedNearbyIndex < 0 || _selectedNearbyIndex >= _nearbySyncshells.Count)
|
|
return null;
|
|
|
|
return _nearbySyncshells[_selectedNearbyIndex].Group.GID;
|
|
}
|
|
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
base.Dispose(disposing);
|
|
}
|
|
}
|