fix banning modal, fix disposal async calls to penumbra
This commit is contained in:
@@ -141,96 +141,14 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
|
|||||||
|
|
||||||
public bool CheckCustomizePlusApi() => _customizePlusAvailable;
|
public bool CheckCustomizePlusApi() => _customizePlusAvailable;
|
||||||
|
|
||||||
private bool CheckCustomizePlusApiInternal()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return string.Equals(_customizePlusApiVersion.InvokeFunc(), "1.0", StringComparison.Ordinal);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CheckGlamourerApi() => _glamourerAvailable;
|
public bool CheckGlamourerApi() => _glamourerAvailable;
|
||||||
|
|
||||||
private bool CheckGlamourerApiInternal()
|
|
||||||
{
|
|
||||||
bool apiAvailable = false;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
apiAvailable = _glamourerApiVersion.InvokeFunc() >= 0;
|
|
||||||
_shownGlamourerUnavailable = _shownGlamourerUnavailable && !apiAvailable;
|
|
||||||
return apiAvailable;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return apiAvailable;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (!apiAvailable && !_shownGlamourerUnavailable)
|
|
||||||
{
|
|
||||||
_shownGlamourerUnavailable = true;
|
|
||||||
Mediator.Publish(new NotificationMessage("Glamourer inactive", "Your Glamourer installation is not active or out of date. Update Glamourer to continue to use Mare.", NotificationType.Error));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CheckHeelsApi() => _heelsAvailable;
|
public bool CheckHeelsApi() => _heelsAvailable;
|
||||||
|
|
||||||
private bool CheckHeelsApiInternal()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return string.Equals(_heelsGetApiVersion.InvokeFunc(), "1.0.1", StringComparison.Ordinal);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CheckPalettePlusApi() => _palettePlusAvailable;
|
public bool CheckPalettePlusApi() => _palettePlusAvailable;
|
||||||
|
|
||||||
private bool CheckPalettePlusApiInternal()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return string.Equals(_palettePlusApiVersion.InvokeFunc(), "1.1.0", StringComparison.Ordinal);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CheckPenumbraApi() => _penumbraAvailable;
|
public bool CheckPenumbraApi() => _penumbraAvailable;
|
||||||
|
|
||||||
private bool CheckPenumbraApiInternal()
|
|
||||||
{
|
|
||||||
bool apiAvailable = false;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
apiAvailable = _penumbraApiVersion.Invoke() is { Item1: 4, Item2: >= 19 } && _penumbraEnabled.Invoke();
|
|
||||||
_shownPenumbraUnavailable = _shownPenumbraUnavailable && !apiAvailable;
|
|
||||||
return apiAvailable;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return apiAvailable;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (!apiAvailable && !_shownPenumbraUnavailable)
|
|
||||||
{
|
|
||||||
_shownPenumbraUnavailable = true;
|
|
||||||
Mediator.Publish(new NotificationMessage("Penumbra inactive", "Your Penumbra installation is not active or out of date. Update Penumbra and/or the Enable Mods setting in Penumbra to continue to use Mare.", NotificationType.Error));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task CustomizePlusRevert(IntPtr character)
|
public async Task CustomizePlusRevert(IntPtr character)
|
||||||
{
|
{
|
||||||
if (!CheckCustomizePlusApi()) return;
|
if (!CheckCustomizePlusApi()) return;
|
||||||
@@ -274,12 +192,6 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
|
|||||||
return _heelsGetOffset.InvokeFunc();
|
return _heelsGetOffset.InvokeFunc();
|
||||||
}
|
}
|
||||||
|
|
||||||
private string? GetPenumbraModDirectoryInternal()
|
|
||||||
{
|
|
||||||
if (!CheckPenumbraApi()) return null;
|
|
||||||
return _penumbraResolveModDir!.Invoke().ToLowerInvariant();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task GlamourerApplyAll(ILogger logger, GameObjectHandler handler, string? customization, Guid applicationId, CancellationToken token, bool fireAndForget = false)
|
public async Task GlamourerApplyAll(ILogger logger, GameObjectHandler handler, string? customization, Guid applicationId, CancellationToken token, bool fireAndForget = false)
|
||||||
{
|
{
|
||||||
if (!CheckGlamourerApi() || string.IsNullOrEmpty(customization) || _dalamudUtil.IsZoning) return;
|
if (!CheckGlamourerApi() || string.IsNullOrEmpty(customization) || _dalamudUtil.IsZoning) return;
|
||||||
@@ -423,38 +335,44 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PenumbraRemoveTemporaryCollection(ILogger logger, Guid applicationId, string characterName)
|
public async Task PenumbraRemoveTemporaryCollection(ILogger logger, Guid applicationId, string characterName)
|
||||||
{
|
{
|
||||||
if (!CheckPenumbraApi()) return;
|
if (!CheckPenumbraApi()) return;
|
||||||
var collName = "Mare_" + characterName;
|
await _dalamudUtil.RunOnFrameworkThread(() =>
|
||||||
logger.LogTrace("[{applicationId}] Removing temp collection for {collName}", applicationId, collName);
|
{
|
||||||
var ret = _penumbraRemoveTemporaryMod.Invoke("MareChara", collName, 0);
|
var collName = "Mare_" + characterName;
|
||||||
logger.LogTrace("[{applicationId}] RemoveTemporaryMod: {ret}", applicationId, ret);
|
logger.LogTrace("[{applicationId}] Removing temp collection for {collName}", applicationId, collName);
|
||||||
var ret2 = _penumbraRemoveTemporaryCollection.Invoke(collName);
|
var ret = _penumbraRemoveTemporaryMod.Invoke("MareChara", collName, 0);
|
||||||
logger.LogTrace("[{applicationId}] RemoveTemporaryCollection: {ret2}", applicationId, ret2);
|
logger.LogTrace("[{applicationId}] RemoveTemporaryMod: {ret}", applicationId, ret);
|
||||||
|
var ret2 = _penumbraRemoveTemporaryCollection.Invoke(collName);
|
||||||
|
logger.LogTrace("[{applicationId}] RemoveTemporaryCollection: {ret2}", applicationId, ret2);
|
||||||
|
}).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(string[] forward, string[][] reverse)> PenumbraResolvePaths(string[] forward, string[] reverse)
|
public async Task<(string[] forward, string[][] reverse)> PenumbraResolvePaths(string[] forward, string[] reverse)
|
||||||
{
|
{
|
||||||
return await _dalamudUtil.RunOnFrameworkThread(() => _penumbraResolvePaths.Invoke(forward, reverse));
|
return await _dalamudUtil.RunOnFrameworkThread(() => _penumbraResolvePaths.Invoke(forward, reverse)).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PenumbraSetTemporaryMods(ILogger logger, Guid applicationId, string characterName, int? idx, Dictionary<string, string> modPaths, string manipulationData)
|
public async Task PenumbraSetTemporaryMods(ILogger logger, Guid applicationId, string characterName, int? idx, Dictionary<string, string> modPaths, string manipulationData)
|
||||||
{
|
{
|
||||||
if (!CheckPenumbraApi() || idx == null) return;
|
if (!CheckPenumbraApi() || idx == null) return;
|
||||||
|
|
||||||
var collName = "Mare_" + characterName;
|
await _dalamudUtil.RunOnFrameworkThread(() =>
|
||||||
var ret = _penumbraCreateNamedTemporaryCollection.Invoke(collName);
|
|
||||||
logger.LogTrace("[{applicationId}] Creating Temp Collection {collName}, Success: {ret}", applicationId, collName, ret);
|
|
||||||
var retAssign = _penumbraAssignTemporaryCollection.Invoke(collName, idx.Value, c: true);
|
|
||||||
logger.LogTrace("[{applicationId}] Assigning Temp Collection {collName} to index {idx}, Success: {ret}", applicationId, collName, idx, retAssign);
|
|
||||||
foreach (var mod in modPaths)
|
|
||||||
{
|
{
|
||||||
logger.LogTrace("[{applicationId}] Change: {from} => {to}", applicationId, mod.Key, mod.Value);
|
var collName = "Mare_" + characterName;
|
||||||
}
|
var ret = _penumbraCreateNamedTemporaryCollection.Invoke(collName);
|
||||||
|
logger.LogTrace("[{applicationId}] Creating Temp Collection {collName}, Success: {ret}", applicationId, collName, ret);
|
||||||
|
var retAssign = _penumbraAssignTemporaryCollection.Invoke(collName, idx.Value, c: true);
|
||||||
|
logger.LogTrace("[{applicationId}] Assigning Temp Collection {collName} to index {idx}, Success: {ret}", applicationId, collName, idx, retAssign);
|
||||||
|
foreach (var mod in modPaths)
|
||||||
|
{
|
||||||
|
logger.LogTrace("[{applicationId}] Change: {from} => {to}", applicationId, mod.Key, mod.Value);
|
||||||
|
}
|
||||||
|
|
||||||
var ret2 = _penumbraAddTemporaryMod.Invoke("MareChara", collName, modPaths, manipulationData, 0);
|
var ret2 = _penumbraAddTemporaryMod.Invoke("MareChara", collName, modPaths, manipulationData, 0);
|
||||||
logger.LogTrace("[{applicationId}] Setting temp mods for {collName}, Success: {ret2}", applicationId, collName, ret2);
|
logger.LogTrace("[{applicationId}] Setting temp mods for {collName}, Success: {ret2}", applicationId, collName, ret2);
|
||||||
|
}).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ToggleGposeQueueMode(bool on)
|
public void ToggleGposeQueueMode(bool on)
|
||||||
@@ -498,12 +416,100 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
|
|||||||
_customizePlusOnScaleUpdate.Unsubscribe(OnCustomizePlusScaleChange);
|
_customizePlusOnScaleUpdate.Unsubscribe(OnCustomizePlusScaleChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool CheckCustomizePlusApiInternal()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return string.Equals(_customizePlusApiVersion.InvokeFunc(), "1.0", StringComparison.Ordinal);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CheckGlamourerApiInternal()
|
||||||
|
{
|
||||||
|
bool apiAvailable = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
apiAvailable = _glamourerApiVersion.InvokeFunc() >= 0;
|
||||||
|
_shownGlamourerUnavailable = _shownGlamourerUnavailable && !apiAvailable;
|
||||||
|
return apiAvailable;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return apiAvailable;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (!apiAvailable && !_shownGlamourerUnavailable)
|
||||||
|
{
|
||||||
|
_shownGlamourerUnavailable = true;
|
||||||
|
Mediator.Publish(new NotificationMessage("Glamourer inactive", "Your Glamourer installation is not active or out of date. Update Glamourer to continue to use Mare.", NotificationType.Error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CheckHeelsApiInternal()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return string.Equals(_heelsGetApiVersion.InvokeFunc(), "1.0.1", StringComparison.Ordinal);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CheckPalettePlusApiInternal()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return string.Equals(_palettePlusApiVersion.InvokeFunc(), "1.1.0", StringComparison.Ordinal);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CheckPenumbraApiInternal()
|
||||||
|
{
|
||||||
|
bool apiAvailable = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
apiAvailable = _penumbraApiVersion.Invoke() is { Item1: 4, Item2: >= 19 } && _penumbraEnabled.Invoke();
|
||||||
|
_shownPenumbraUnavailable = _shownPenumbraUnavailable && !apiAvailable;
|
||||||
|
return apiAvailable;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return apiAvailable;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (!apiAvailable && !_shownPenumbraUnavailable)
|
||||||
|
{
|
||||||
|
_shownPenumbraUnavailable = true;
|
||||||
|
Mediator.Publish(new NotificationMessage("Penumbra inactive", "Your Penumbra installation is not active or out of date. Update Penumbra and/or the Enable Mods setting in Penumbra to continue to use Mare.", NotificationType.Error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void ClearActionQueue()
|
private void ClearActionQueue()
|
||||||
{
|
{
|
||||||
ActionQueue.Clear();
|
ActionQueue.Clear();
|
||||||
_gposeActionQueue.Clear();
|
_gposeActionQueue.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string? GetPenumbraModDirectoryInternal()
|
||||||
|
{
|
||||||
|
if (!CheckPenumbraApi()) return null;
|
||||||
|
return _penumbraResolveModDir!.Invoke().ToLowerInvariant();
|
||||||
|
}
|
||||||
|
|
||||||
private void HandleActionQueue()
|
private void HandleActionQueue()
|
||||||
{
|
{
|
||||||
if (ActionQueue.TryDequeue(out var action))
|
if (ActionQueue.TryDequeue(out var action))
|
||||||
@@ -564,7 +570,7 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
|
|||||||
{
|
{
|
||||||
if (!fireAndForget)
|
if (!fireAndForget)
|
||||||
{
|
{
|
||||||
await _dalamudUtil.RunOnFrameworkThread(action);
|
await _dalamudUtil.RunOnFrameworkThread(action).ConfigureAwait(false);
|
||||||
|
|
||||||
var disposeToken = _disposalCts.Token;
|
var disposeToken = _disposalCts.Token;
|
||||||
var combinedToken = CancellationTokenSource.CreateLinkedTokenSource(disposeToken, token).Token;
|
var combinedToken = CancellationTokenSource.CreateLinkedTokenSource(disposeToken, token).Token;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Authors></Authors>
|
<Authors></Authors>
|
||||||
<Company></Company>
|
<Company></Company>
|
||||||
<Version>0.8.19</Version>
|
<Version>0.8.20</Version>
|
||||||
<Description></Description>
|
<Description></Description>
|
||||||
<Copyright></Copyright>
|
<Copyright></Copyright>
|
||||||
<PackageProjectUrl>https://github.com/Penumbra-Sync/client</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/Penumbra-Sync/client</PackageProjectUrl>
|
||||||
|
|||||||
@@ -64,14 +64,14 @@ public class MareCharaFileManager
|
|||||||
}
|
}
|
||||||
var applicationId = Guid.NewGuid();
|
var applicationId = Guid.NewGuid();
|
||||||
_ipcManager.ToggleGposeQueueMode(on: true);
|
_ipcManager.ToggleGposeQueueMode(on: true);
|
||||||
_ipcManager.PenumbraRemoveTemporaryCollection(_logger, applicationId, charaTarget.Name.TextValue);
|
await _ipcManager.PenumbraRemoveTemporaryCollection(_logger, applicationId, charaTarget.Name.TextValue).ConfigureAwait(false);
|
||||||
_ipcManager.PenumbraSetTemporaryMods(_logger, applicationId, charaTarget.Name.TextValue, charaTarget.ObjectTableIndex(),
|
await _ipcManager.PenumbraSetTemporaryMods(_logger, applicationId, charaTarget.Name.TextValue, charaTarget.ObjectTableIndex(),
|
||||||
extractedFiles.Union(fileSwaps).ToDictionary(d => d.Key, d => d.Value, StringComparer.Ordinal),
|
extractedFiles.Union(fileSwaps).ToDictionary(d => d.Key, d => d.Value, StringComparer.Ordinal),
|
||||||
LoadedCharaFile.CharaFileData.ManipulationData);
|
LoadedCharaFile.CharaFileData.ManipulationData).ConfigureAwait(false);
|
||||||
using GameObjectHandler tempHandler = _gameObjectHandlerFactory(ObjectKind.Player, () => charaTarget.Address, false);
|
using GameObjectHandler tempHandler = _gameObjectHandlerFactory(ObjectKind.Player, () => charaTarget.Address, false);
|
||||||
await _ipcManager.GlamourerApplyAll(_logger, tempHandler, LoadedCharaFile.CharaFileData.GlamourerData, applicationId, disposeCts.Token).ConfigureAwait(false);
|
await _ipcManager.GlamourerApplyAll(_logger, tempHandler, LoadedCharaFile.CharaFileData.GlamourerData, applicationId, disposeCts.Token).ConfigureAwait(false);
|
||||||
_dalamudUtil.WaitWhileGposeCharacterIsDrawing(charaTarget.Address, 30000);
|
_dalamudUtil.WaitWhileGposeCharacterIsDrawing(charaTarget.Address, 30000);
|
||||||
_ipcManager.PenumbraRemoveTemporaryCollection(_logger, applicationId, charaTarget.Name.TextValue);
|
await _ipcManager.PenumbraRemoveTemporaryCollection(_logger, applicationId, charaTarget.Name.TextValue).ConfigureAwait(false);
|
||||||
_ipcManager.ToggleGposeQueueMode(on: false);
|
_ipcManager.ToggleGposeQueueMode(on: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -176,12 +176,12 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
|
|||||||
if (_dalamudUtil.IsZoning)
|
if (_dalamudUtil.IsZoning)
|
||||||
{
|
{
|
||||||
Logger.LogTrace("[{applicationId}] Removing temp collection for {name} ({OnlineUser})", applicationId, name, OnlineUser);
|
Logger.LogTrace("[{applicationId}] Removing temp collection for {name} ({OnlineUser})", applicationId, name, OnlineUser);
|
||||||
_ipcManager.PenumbraRemoveTemporaryCollection(Logger, applicationId, name);
|
_ipcManager.PenumbraRemoveTemporaryCollection(Logger, applicationId, name).GetAwaiter().GetResult();
|
||||||
}
|
}
|
||||||
else if (_dalamudUtil is { IsZoning: false, IsInCutscene: false })
|
else if (_dalamudUtil is { IsZoning: false, IsInCutscene: false })
|
||||||
{
|
{
|
||||||
Logger.LogTrace("[{applicationId}] Restoring state for {name} ({OnlineUser})", applicationId, name, OnlineUser);
|
Logger.LogTrace("[{applicationId}] Restoring state for {name} ({OnlineUser})", applicationId, name, OnlineUser);
|
||||||
_ipcManager.PenumbraRemoveTemporaryCollection(Logger, applicationId, name);
|
_ipcManager.PenumbraRemoveTemporaryCollection(Logger, applicationId, name).GetAwaiter().GetResult();
|
||||||
|
|
||||||
foreach (KeyValuePair<ObjectKind, List<FileReplacementData>> item in _cachedData.FileReplacements)
|
foreach (KeyValuePair<ObjectKind, List<FileReplacementData>> item in _cachedData.FileReplacements)
|
||||||
{
|
{
|
||||||
@@ -211,10 +211,10 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
|
|||||||
|
|
||||||
private async Task ApplyBaseData(Guid applicationId, Dictionary<string, string> moddedPaths, string manipulationData, CancellationToken token)
|
private async Task ApplyBaseData(Guid applicationId, Dictionary<string, string> moddedPaths, string manipulationData, CancellationToken token)
|
||||||
{
|
{
|
||||||
await _dalamudUtil.RunOnFrameworkThread(() => _ipcManager.PenumbraRemoveTemporaryCollection(Logger, applicationId, PlayerName!)).ConfigureAwait(false);
|
await _ipcManager.PenumbraRemoveTemporaryCollection(Logger, applicationId, PlayerName!).ConfigureAwait(false);
|
||||||
token.ThrowIfCancellationRequested();
|
token.ThrowIfCancellationRequested();
|
||||||
await _dalamudUtil.RunOnFrameworkThread(() => _ipcManager.PenumbraSetTemporaryMods(Logger, applicationId, PlayerName!,
|
await _ipcManager.PenumbraSetTemporaryMods(Logger, applicationId, PlayerName!,
|
||||||
_charaHandler?.GameObjectLazy?.Value.ObjectTableIndex(), moddedPaths, manipulationData)).ConfigureAwait(false);
|
_charaHandler?.GameObjectLazy?.Value.ObjectTableIndex(), moddedPaths, manipulationData).ConfigureAwait(false);
|
||||||
token.ThrowIfCancellationRequested();
|
token.ThrowIfCancellationRequested();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,11 +14,11 @@ namespace MareSynchronos.UI.Components;
|
|||||||
|
|
||||||
public class DrawGroupPair : DrawPairBase
|
public class DrawGroupPair : DrawPairBase
|
||||||
{
|
{
|
||||||
|
private static string _banReason = string.Empty;
|
||||||
|
private static bool _banUserPopupOpen;
|
||||||
|
private static bool _showModalBanUser;
|
||||||
private readonly GroupPairFullInfoDto _fullInfoDto;
|
private readonly GroupPairFullInfoDto _fullInfoDto;
|
||||||
private readonly GroupFullInfoDto _group;
|
private readonly GroupFullInfoDto _group;
|
||||||
private string _banReason = string.Empty;
|
|
||||||
private bool _banUserPopupOpen;
|
|
||||||
private bool _showModalBanUser;
|
|
||||||
|
|
||||||
public DrawGroupPair(string id, Pair entry, ApiController apiController, GroupFullInfoDto group, GroupPairFullInfoDto fullInfoDto, UidDisplayHandler handler) : base(id, entry, apiController, handler)
|
public DrawGroupPair(string id, Pair entry, ApiController apiController, GroupFullInfoDto group, GroupPairFullInfoDto fullInfoDto, UidDisplayHandler handler) : base(id, entry, apiController, handler)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user