Fixed context menu items, made static function for it to be used

This commit is contained in:
cake
2025-11-29 22:42:55 +01:00
parent 740b58afc4
commit 1e88fe0cf3
3 changed files with 90 additions and 63 deletions

View File

@@ -6,8 +6,9 @@ using LightlessSync.API.Data.Extensions;
using LightlessSync.API.Dto.User; using LightlessSync.API.Dto.User;
using LightlessSync.Services.Mediator; using LightlessSync.Services.Mediator;
using LightlessSync.Services.ServerConfiguration; using LightlessSync.Services.ServerConfiguration;
using Microsoft.Extensions.Logging; using LightlessSync.UI;
using LightlessSync.WebAPI; using LightlessSync.WebAPI;
using Microsoft.Extensions.Logging;
namespace LightlessSync.PlayerData.Pairs; namespace LightlessSync.PlayerData.Pairs;
@@ -22,6 +23,8 @@ public class Pair
private readonly ServerConfigurationManager _serverConfigurationManager; private readonly ServerConfigurationManager _serverConfigurationManager;
private readonly Lazy<ApiController> _apiController; private readonly Lazy<ApiController> _apiController;
private const int _lightlessPrefixColor = 708;
public Pair( public Pair(
ILogger<Pair> logger, ILogger<Pair> logger,
UserFullPairDto userPair, UserFullPairDto userPair,
@@ -89,48 +92,28 @@ public class Pair
return; return;
} }
var openProfileSeString = new SeStringBuilder().AddText("Open Profile").Build(); UiSharedService.AddContextMenuItem(args, name: "Open Profile", prefixChar: 'L', colorMenuItem: _lightlessPrefixColor, onClick: () =>
var reapplyDataSeString = new SeStringBuilder().AddText("Reapply last data").Build();
var cyclePauseState = new SeStringBuilder().AddText("Cycle pause state").Build();
var changePermissions = new SeStringBuilder().AddText("Change Permissions").Build();
args.AddMenuItem(new MenuItem
{ {
Name = openProfileSeString, _mediator.Publish(new ProfileOpenStandaloneMessage(this));
OnClicked = _ => _mediator.Publish(new ProfileOpenStandaloneMessage(this)), return Task.CompletedTask;
UseDefaultPrefix = false,
PrefixChar = 'L',
PrefixColor = 708
}); });
args.AddMenuItem(new MenuItem UiSharedService.AddContextMenuItem(args, name: "Reapply last data", prefixChar: 'L', colorMenuItem: _lightlessPrefixColor, onClick: () =>
{ {
Name = reapplyDataSeString, ApplyLastReceivedData(forced: true);
OnClicked = _ => ApplyLastReceivedData(forced: true), return Task.CompletedTask;
UseDefaultPrefix = false,
PrefixChar = 'L',
PrefixColor = 708
}); });
args.AddMenuItem(new MenuItem UiSharedService.AddContextMenuItem(args, name: "Change Permissions", prefixChar: 'L', colorMenuItem: _lightlessPrefixColor, onClick: () =>
{ {
Name = changePermissions, _mediator.Publish(new OpenPermissionWindow(this));
OnClicked = _ => _mediator.Publish(new OpenPermissionWindow(this)), return Task.CompletedTask;
UseDefaultPrefix = false,
PrefixChar = 'L',
PrefixColor = 708
}); });
args.AddMenuItem(new MenuItem UiSharedService.AddContextMenuItem(args, name: "Cycle pause state", prefixChar: 'L', colorMenuItem: _lightlessPrefixColor, onClick: () =>
{
Name = cyclePauseState,
OnClicked = _ =>
{ {
TriggerCyclePause(); TriggerCyclePause();
}, return Task.CompletedTask;
UseDefaultPrefix = false,
PrefixChar = 'L',
PrefixColor = 708
}); });
} }

View File

@@ -1,5 +1,4 @@
using LightlessSync; using Dalamud.Game.ClientState.Objects.SubKinds;
using Dalamud.Game.ClientState.Objects.SubKinds;
using Dalamud.Game.Gui.ContextMenu; using Dalamud.Game.Gui.ContextMenu;
using Dalamud.Plugin; using Dalamud.Plugin;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
@@ -12,6 +11,7 @@ using Lumina.Excel.Sheets;
using LightlessSync.UI.Services; using LightlessSync.UI.Services;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using LightlessSync.UI;
namespace LightlessSync.Services; namespace LightlessSync.Services;
@@ -33,6 +33,8 @@ internal class ContextMenuService : IHostedService
private readonly LightlessProfileManager _lightlessProfileManager; private readonly LightlessProfileManager _lightlessProfileManager;
private readonly LightlessMediator _mediator; private readonly LightlessMediator _mediator;
private const int _lightlessPrefixColor = 708;
public ContextMenuService( public ContextMenuService(
IContextMenu contextMenu, IContextMenu contextMenu,
IDalamudPluginInterface pluginInterface, IDalamudPluginInterface pluginInterface,
@@ -97,44 +99,74 @@ internal class ContextMenuService : IHostedService
return; return;
if (args.AddonName != null) if (args.AddonName != null)
{
var addonName = args.AddonName;
_logger.LogTrace("Context menu addon name: {AddonName}", addonName);
return; return;
}
if (args.Target is not MenuTargetDefault target) if (args.Target is not MenuTargetDefault target)
{
_logger.LogTrace("Context menu target is not MenuTargetDefault.");
return; return;
}
_logger.LogTrace("Context menu opened for target: {Target}", target.TargetName ?? "null");
if (string.IsNullOrEmpty(target.TargetName) || target.TargetObjectId == 0 || target.TargetHomeWorld.RowId == 0) if (string.IsNullOrEmpty(target.TargetName) || target.TargetObjectId == 0 || target.TargetHomeWorld.RowId == 0)
{
_logger.LogTrace("Context menu target has invalid data: Name='{TargetName}', ObjectId={TargetObjectId}, HomeWorldId={TargetHomeWorldId}", target.TargetName, target.TargetObjectId, target.TargetHomeWorld.RowId);
return; return;
}
IPlayerCharacter? targetData = GetPlayerFromObjectTable(target); IPlayerCharacter? targetData = GetPlayerFromObjectTable(target);
if (targetData == null || targetData.Address == nint.Zero || _clientState.LocalPlayer == null) if (targetData == null || targetData.Address == nint.Zero || _objectTable.LocalPlayer == null)
return; {
_logger.LogTrace("Target player {TargetName}@{World} not found in object table.", target.TargetName, target.TargetHomeWorld.RowId);
//Check if user is directly paired or is own.
if (VisibleUserIds.Any(u => u == target.TargetObjectId) || _clientState.LocalPlayer.GameObjectId == target.TargetObjectId || !_configService.Current.EnableRightClickMenus)
return; return;
}
var snapshot = _pairUiService.GetSnapshot(); var snapshot = _pairUiService.GetSnapshot();
var pair = snapshot.PairsByUid.Values.FirstOrDefault(p => var pair = snapshot.PairsByUid.Values.FirstOrDefault(p =>
p.IsVisible && p.IsVisible &&
p.PlayerCharacterId != uint.MaxValue && p.PlayerCharacterId != uint.MaxValue &&
(ulong)p.PlayerCharacterId == target.TargetObjectId); p.PlayerCharacterId == target.TargetObjectId);
if (pair is not null) if (pair is not null)
{ {
_logger.LogTrace("Target player {TargetName}@{World} is already paired, adding existing pair context menu.", target.TargetName, target.TargetHomeWorld.RowId);
pair.AddContextMenu(args); pair.AddContextMenu(args);
if (!pair.IsDirectlyPaired)
{
_logger.LogTrace("Target player {TargetName}@{World} is not directly paired, add direct pair menu item", target.TargetName, target.TargetHomeWorld.RowId);
AddDirectPairMenuItem(args);
}
return; return;
} }
_logger.LogTrace("Target player {TargetName}@{World} is not paired, adding direct pair request context menu.", target.TargetName, target.TargetHomeWorld.RowId);
//Check if user is directly paired or is own. //Check if user is directly paired or is own.
if (VisibleUserIds.Contains(target.TargetObjectId) || (_clientState.LocalPlayer?.GameObjectId ?? 0) == target.TargetObjectId) if (VisibleUserIds.Any(u => u == target.TargetObjectId) || _objectTable.LocalPlayer?.GameObjectId == target.TargetObjectId || !_configService.Current.EnableRightClickMenus)
{
_logger.LogTrace("Target player {TargetName}@{World} is already paired or is self, or right-click menus are disabled.", target.TargetName, target.TargetHomeWorld.RowId);
return; return;
}
if (_clientState.IsPvPExcludingDen || _clientState.IsGPosing) if (_clientState.IsPvPExcludingDen || _clientState.IsGPosing)
{
_logger.LogTrace("Cannot send pair request to {TargetName}@{World} while in PvP or GPose.", target.TargetName, target.TargetHomeWorld.RowId);
return; return;
}
var world = GetWorld(target.TargetHomeWorld.RowId); var world = GetWorld(target.TargetHomeWorld.RowId);
if (!IsWorldValid(world)) if (!IsWorldValid(world))
{
_logger.LogTrace("Target player {TargetName}@{World} is on an invalid world.", target.TargetName, target.TargetHomeWorld.RowId);
return; return;
}
string? targetHashedCid = null; string? targetHashedCid = null;
if (_broadcastService.IsBroadcasting) if (_broadcastService.IsBroadcasting)
@@ -145,31 +177,26 @@ internal class ContextMenuService : IHostedService
if (!string.IsNullOrEmpty(targetHashedCid) && CanOpenLightfinderProfile(targetHashedCid)) if (!string.IsNullOrEmpty(targetHashedCid) && CanOpenLightfinderProfile(targetHashedCid))
{ {
var hashedCid = targetHashedCid; var hashedCid = targetHashedCid;
args.AddMenuItem(new MenuItem UiSharedService.AddContextMenuItem(args, name: "Open Lightless Profile", prefixChar: 'L', colorMenuItem: _lightlessPrefixColor, onClick: () => HandleLightfinderProfileSelection(hashedCid));
{
Name = "Open Lightless Profile",
PrefixChar = 'L',
UseDefaultPrefix = false,
PrefixColor = 708,
OnClicked = async _ => await HandleLightfinderProfileSelection(hashedCid!).ConfigureAwait(false)
});
} }
args.AddMenuItem(new MenuItem AddDirectPairMenuItem(args);
}
private void AddDirectPairMenuItem(IMenuOpenedArgs args)
{ {
Name = "Send Direct Pair Request", UiSharedService.AddContextMenuItem(
PrefixChar = 'L', args,
UseDefaultPrefix = false, name: "Send Direct Pair Request",
PrefixColor = 708, prefixChar: 'L',
OnClicked = _ => HandleSelection(args).ConfigureAwait(false).GetAwaiter().GetResult() colorMenuItem: _lightlessPrefixColor,
}); onClick: () => HandleSelection(args));
} }
private HashSet<ulong> VisibleUserIds => private HashSet<ulong> VisibleUserIds =>
_pairUiService.GetSnapshot().PairsByUid.Values [.. _pairUiService.GetSnapshot().PairsByUid.Values
.Where(p => p.IsVisible && p.PlayerCharacterId != uint.MaxValue) .Where(p => p.IsVisible && p.PlayerCharacterId != uint.MaxValue)
.Select(p => (ulong)p.PlayerCharacterId) .Select(p => (ulong)p.PlayerCharacterId)];
.ToHashSet();
private async Task HandleSelection(IMenuArgs args) private async Task HandleSelection(IMenuArgs args)
{ {

View File

@@ -1,4 +1,6 @@
using Dalamud.Bindings.ImGui; using Dalamud.Bindings.ImGui;
using Dalamud.Game.Gui.ContextMenu;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Interface; using Dalamud.Interface;
using Dalamud.Interface.Colors; using Dalamud.Interface.Colors;
using Dalamud.Interface.GameFonts; using Dalamud.Interface.GameFonts;
@@ -8,7 +10,6 @@ using Dalamud.Interface.Textures;
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 System;
using Dalamud.Plugin; using Dalamud.Plugin;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using Dalamud.Utility; using Dalamud.Utility;
@@ -25,6 +26,7 @@ using LightlessSync.Utils;
using LightlessSync.WebAPI; using LightlessSync.WebAPI;
using LightlessSync.WebAPI.SignalR; using LightlessSync.WebAPI.SignalR;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System;
using System.IdentityModel.Tokens.Jwt; using System.IdentityModel.Tokens.Jwt;
using System.Numerics; using System.Numerics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@@ -487,6 +489,21 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
); );
} }
public static void AddContextMenuItem(IMenuOpenedArgs args, SeString name, char prefixChar, ushort colorMenuItem, Func<Task> onClick)
{
args.AddMenuItem(new MenuItem
{
Name = name,
PrefixChar = prefixChar,
UseDefaultPrefix = false,
PrefixColor = colorMenuItem,
OnClicked = _ =>
{
onClick();
},
});
}
public static 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 drawList = ImGui.GetWindowDrawList();