Ajout de la gestion avancée de l'indicateur de frappe et des paramètres associés

This commit is contained in:
2025-11-02 17:21:25 +01:00
parent 699678f641
commit e3d9300ca3
9 changed files with 221 additions and 48 deletions

View File

@@ -52,6 +52,8 @@ public class SettingsUi : WindowMediatorSubscriberBase
private readonly AccountRegistrationService _registerService;
private readonly ServerConfigurationManager _serverConfigurationManager;
private readonly UiSharedService _uiShared;
private readonly TypingIndicatorStateService _typingStateService;
private readonly ChatTypingDetectionService _chatTypingDetectionService;
private static readonly string DtrDefaultPreviewText = DtrEntry.DefaultGlyph + " 123";
private bool _deleteAccountPopupModalShown = false;
private string _lastTab = string.Empty;
@@ -80,7 +82,9 @@ public class SettingsUi : WindowMediatorSubscriberBase
FileCompactor fileCompactor, ApiController apiController,
IpcManager ipcManager, IpcProvider ipcProvider, CacheMonitor cacheMonitor,
DalamudUtilService dalamudUtilService, AccountRegistrationService registerService,
AutoDetectSuppressionService autoDetectSuppressionService) : base(logger, mediator, "Umbra Settings", performanceCollector)
AutoDetectSuppressionService autoDetectSuppressionService,
TypingIndicatorStateService typingIndicatorStateService,
ChatTypingDetectionService chatTypingDetectionService) : base(logger, mediator, "Umbra Settings", performanceCollector)
{
_configService = configService;
_pairManager = pairManager;
@@ -102,6 +106,8 @@ public class SettingsUi : WindowMediatorSubscriberBase
_autoDetectSuppressionService = autoDetectSuppressionService;
_fileCompactor = fileCompactor;
_uiShared = uiShared;
_typingStateService = typingIndicatorStateService;
_chatTypingDetectionService = chatTypingDetectionService;
AllowClickthrough = false;
AllowPinning = false;
_validationProgress = new Progress<(int, int, FileCacheEntity)>(v => _currentProgress = v);
@@ -1123,8 +1129,10 @@ public class SettingsUi : WindowMediatorSubscriberBase
var useNameColors = _configService.Current.UseNameColors;
var nameColors = _configService.Current.NameColors;
var autoPausedNameColors = _configService.Current.BlockedNameColors;
var typingEnabled = _configService.Current.TypingIndicatorEnabled;
var typingIndicatorNameplates = _configService.Current.TypingIndicatorShowOnNameplates;
var typingIndicatorPartyList = _configService.Current.TypingIndicatorShowOnPartyList;
var typingShowSelf = _configService.Current.TypingIndicatorShowSelf;
if (ImGui.Checkbox("Coloriser les plaques de nom des paires", ref useNameColors))
{
_configService.Current.UseNameColors = useNameColors;
@@ -1152,42 +1160,67 @@ public class SettingsUi : WindowMediatorSubscriberBase
}
}
if (ImGui.Checkbox("Afficher la bulle de frappe sur les plaques", ref typingIndicatorNameplates))
if (ImGui.Checkbox("Activer le système d'indicateur de frappe", ref typingEnabled))
{
_configService.Current.TypingIndicatorShowOnNameplates = typingIndicatorNameplates;
_configService.Current.TypingIndicatorEnabled = typingEnabled;
_configService.Save();
_chatTypingDetectionService.SoftRestart();
}
_uiShared.DrawHelpText("Ajoute une bulle '...' sur la plaque des paires en train d'écrire.");
_uiShared.DrawHelpText("Active ou désactive complètement l'envoi/la réception et l'affichage des bulles de frappe.");
using (ImRaii.Disabled(!typingIndicatorNameplates))
using (ImRaii.Disabled(!typingEnabled))
{
using var indentTyping = ImRaii.PushIndent();
var bubbleSize = _configService.Current.TypingIndicatorBubbleSize;
TypingIndicatorBubbleSize? selectedBubbleSize = _uiShared.DrawCombo("Taille de la bulle de frappe##typingBubbleSize",
Enum.GetValues<TypingIndicatorBubbleSize>(),
size => size switch
{
TypingIndicatorBubbleSize.Small => "Petite",
TypingIndicatorBubbleSize.Medium => "Moyenne",
TypingIndicatorBubbleSize.Large => "Grande",
_ => size.ToString()
},
null,
bubbleSize);
if (selectedBubbleSize.HasValue && selectedBubbleSize.Value != bubbleSize)
if (ImGui.Checkbox("Afficher la bulle de frappe sur les plaques", ref typingIndicatorNameplates))
{
_configService.Current.TypingIndicatorBubbleSize = selectedBubbleSize.Value;
_configService.Current.TypingIndicatorShowOnNameplates = typingIndicatorNameplates;
_configService.Save();
}
}
_uiShared.DrawHelpText("Ajoute une bulle '...' sur la plaque des paires en train d'écrire.");
if (ImGui.Checkbox("Tracer la frappe dans la liste de groupe", ref typingIndicatorPartyList))
{
_configService.Current.TypingIndicatorShowOnPartyList = typingIndicatorPartyList;
_configService.Save();
using (ImRaii.Disabled(!typingIndicatorNameplates))
{
using var indentTyping = ImRaii.PushIndent();
var bubbleSize = _configService.Current.TypingIndicatorBubbleSize;
TypingIndicatorBubbleSize? selectedBubbleSize = _uiShared.DrawCombo("Taille de la bulle de frappe##typingBubbleSize",
Enum.GetValues<TypingIndicatorBubbleSize>(),
size => size switch
{
TypingIndicatorBubbleSize.Small => "Petite",
TypingIndicatorBubbleSize.Medium => "Moyenne",
TypingIndicatorBubbleSize.Large => "Grande",
_ => size.ToString()
},
null,
bubbleSize);
if (selectedBubbleSize.HasValue && selectedBubbleSize.Value != bubbleSize)
{
_configService.Current.TypingIndicatorBubbleSize = selectedBubbleSize.Value;
_configService.Save();
}
}
if (ImGui.Checkbox("Tracer la frappe dans la liste de groupe", ref typingIndicatorPartyList))
{
_configService.Current.TypingIndicatorShowOnPartyList = typingIndicatorPartyList;
_configService.Save();
}
_uiShared.DrawHelpText("Consigne dans les journaux quand une paire du groupe est en train d'écrire (bulle visuelle ultérieure).");
if (ImGui.Checkbox("Afficher ma propre bulle", ref typingShowSelf))
{
_configService.Current.TypingIndicatorShowSelf = typingShowSelf;
_configService.Save();
}
_uiShared.DrawHelpText("Affiche votre propre bulle lorsque vous tapez (utile pour test/retour visuel).");
if (ImGui.Button("Redémarrer le système de frappe"))
{
_chatTypingDetectionService.SoftRestart();
_guiHookService.RequestRedraw();
}
_uiShared.DrawHelpText("Vide l'état local et réinitialise les timers sans redémarrer le plugin.");
}
_uiShared.DrawHelpText("Consigne dans les journaux quand une paire du groupe est en train d'écrire (bulle visuelle ultérieure).");
if (ImGui.Checkbox("Show separate Visible group", ref showVisibleSeparate))
{

View File

@@ -7,6 +7,7 @@ using Dalamud.Interface.Utility;
using Dalamud.Plugin.Services;
using MareSynchronos.API.Data;
using MareSynchronos.API.Data.Extensions;
using MareSynchronos.API.Data.Enum;
using MareSynchronos.MareConfiguration;
using MareSynchronos.MareConfiguration.Models;
using MareSynchronos.PlayerData.Pairs;
@@ -75,6 +76,10 @@ public sealed class TypingIndicatorOverlay : WindowMediatorSubscriberBase
if (!_clientState.IsLoggedIn)
return;
var typingEnabled = _configService.Current.TypingIndicatorEnabled;
if (!typingEnabled)
return;
var showParty = _configService.Current.TypingIndicatorShowOnPartyList;
var showNameplates = _configService.Current.TypingIndicatorShowOnNameplates;
@@ -97,14 +102,16 @@ public sealed class TypingIndicatorOverlay : WindowMediatorSubscriberBase
}
}
private unsafe void DrawPartyIndicators(ImDrawListPtr drawList, IReadOnlyDictionary<string, (UserData User, DateTime FirstSeen, DateTime LastUpdate)> activeTypers,
private unsafe void DrawPartyIndicators(ImDrawListPtr drawList, IReadOnlyDictionary<string, (UserData User, DateTime FirstSeen, DateTime LastUpdate, MareSynchronos.API.Data.Enum.TypingScope Scope)> activeTypers,
bool selfActive, DateTime now, DateTime selfStart, DateTime selfLast)
{
var partyAddon = (AtkUnitBase*)_gameGui.GetAddonByName("_PartyList", 1).Address;
if (partyAddon == null || !partyAddon->IsVisible)
return;
var showSelf = _configService.Current.TypingIndicatorShowSelf;
if (selfActive
&& showSelf
&& (now - selfStart) >= TypingDisplayDelay
&& (now - selfLast) <= TypingDisplayFade)
{
@@ -180,14 +187,16 @@ public sealed class TypingIndicatorOverlay : WindowMediatorSubscriberBase
ImGui.ColorConvertFloat4ToU32(new Vector4(1f, 1f, 1f, 0.9f)));
}
private unsafe void DrawNameplateIndicators(ImDrawListPtr drawList, IReadOnlyDictionary<string, (UserData User, DateTime FirstSeen, DateTime LastUpdate)> activeTypers,
private unsafe void DrawNameplateIndicators(ImDrawListPtr drawList, IReadOnlyDictionary<string, (UserData User, DateTime FirstSeen, DateTime LastUpdate, MareSynchronos.API.Data.Enum.TypingScope Scope)> activeTypers,
bool selfActive, DateTime now, DateTime selfStart, DateTime selfLast)
{
var iconWrap = _textureProvider.GetFromGameIcon(NameplateIconId).GetWrapOrEmpty();
if (iconWrap == null || iconWrap.Handle == IntPtr.Zero)
return;
var showSelf = _configService.Current.TypingIndicatorShowSelf;
if (selfActive
&& showSelf
&& _clientState.LocalPlayer != null
&& (now - selfStart) >= TypingDisplayDelay
&& (now - selfLast) <= TypingDisplayFade)
@@ -212,11 +221,22 @@ public sealed class TypingIndicatorOverlay : WindowMediatorSubscriberBase
var pairName = pair?.PlayerName ?? entry.User.AliasOrUID ?? string.Empty;
var pairIdent = pair?.Ident ?? string.Empty;
var isPartyMember = IsPartyMember(objectId, pairName);
// Enforce party-only visibility when the scope is Party/CrossParty
if (entry.Scope is TypingScope.Party or TypingScope.CrossParty)
{
if (!isPartyMember)
{
_typedLogger.LogTrace("TypingIndicator: suppressed non-party bubble for {uid} due to scope={scope}", uid, entry.Scope);
continue;
}
}
var isRelevantMember = IsPlayerRelevant(pair, isPartyMember);
if (objectId != uint.MaxValue && objectId != 0 && TryDrawNameplateBubble(drawList, iconWrap, objectId))
{
_typedLogger.LogTrace("TypingIndicator: drew nameplate bubble for {uid} (objectId={objectId})", uid, objectId);
_typedLogger.LogTrace("TypingIndicator: drew nameplate bubble for {uid} (objectId={objectId}, scope={scope})", uid, objectId, entry.Scope);
continue;
}
@@ -226,13 +246,20 @@ public sealed class TypingIndicatorOverlay : WindowMediatorSubscriberBase
if (!isRelevantMember && !isNearby)
continue;
// For Party/CrossParty scope, do not draw fallback world icon for non-party even if nearby
if (entry.Scope is TypingScope.Party or TypingScope.CrossParty)
{
if (!isPartyMember)
continue;
}
if (pair == null)
{
_typedLogger.LogTrace("TypingIndicator: no pair found for {uid}, attempting fallback", uid);
}
_typedLogger.LogTrace("TypingIndicator: fallback draw for {uid} (objectId={objectId}, name={name}, ident={ident})",
uid, objectId, pairName, pairIdent);
_typedLogger.LogTrace("TypingIndicator: fallback draw for {uid} (objectId={objectId}, name={name}, ident={ident}, scope={scope})",
uid, objectId, pairName, pairIdent, entry.Scope);
if (hasWorldPosition)
{