configuration rework
This commit is contained in:
@@ -26,7 +26,7 @@ public class CompactUi : WindowMediatorSubscriberBase, IDisposable
|
||||
private readonly ApiController _apiController;
|
||||
private readonly PairManager _pairManager;
|
||||
private readonly ServerConfigurationManager _serverManager;
|
||||
private readonly ConfigurationService _configService;
|
||||
private readonly MareConfigService _configService;
|
||||
private readonly TagHandler _tagHandler;
|
||||
public readonly Dictionary<string, bool> ShowUidForEntry = new(StringComparer.Ordinal);
|
||||
private readonly UiShared _uiShared;
|
||||
@@ -56,7 +56,7 @@ public class CompactUi : WindowMediatorSubscriberBase, IDisposable
|
||||
private readonly PairGroupsUi _pairGroupsUi;
|
||||
|
||||
public CompactUi(WindowSystem windowSystem,
|
||||
UiShared uiShared, ConfigurationService configService, ApiController apiController, PairManager pairManager,
|
||||
UiShared uiShared, MareConfigService configService, ApiController apiController, PairManager pairManager,
|
||||
ServerConfigurationManager serverManager, MareMediator mediator) : base(mediator, "###MareSynchronosMainUI")
|
||||
{
|
||||
|
||||
@@ -199,8 +199,7 @@ public class CompactUi : WindowMediatorSubscriberBase, IDisposable
|
||||
ImGui.InputTextWithHint("##noteforuser", $"Note for {_lastAddedUser.UserData.AliasOrUID}", ref _lastAddedUserComment, 100);
|
||||
if (UiShared.IconTextButton(FontAwesomeIcon.Save, "Save Note"))
|
||||
{
|
||||
_serverManager.CurrentServer!.UidServerComments[_lastAddedUser.UserData.UID] = _lastAddedUserComment;
|
||||
_serverManager.Save();
|
||||
_serverManager.SetNoteForUid(_lastAddedUser.UserData.UID, _lastAddedUserComment);
|
||||
_lastAddedUser = null;
|
||||
_lastAddedUserComment = string.Empty;
|
||||
_showModalForUserAddition = false;
|
||||
@@ -385,7 +384,8 @@ public class CompactUi : WindowMediatorSubscriberBase, IDisposable
|
||||
|
||||
var textIsUid = true;
|
||||
ShowUidForEntry.TryGetValue(entry.UserPair!.User.UID, out var showUidInsteadOfName);
|
||||
if (!showUidInsteadOfName && _serverManager.CurrentServer!.UidServerComments.TryGetValue(entry.UserPair!.User.UID, out var playerText))
|
||||
string? playerText = _serverManager.GetNoteForUid(entry.UserPair!.User.UID);
|
||||
if (!showUidInsteadOfName && playerText != null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(playerText))
|
||||
{
|
||||
@@ -446,8 +446,7 @@ public class CompactUi : WindowMediatorSubscriberBase, IDisposable
|
||||
ImGui.SetNextItemWidth(UiShared.GetWindowContentRegionWidth() - ImGui.GetCursorPosX() - buttonSizes - ImGui.GetStyle().ItemSpacing.X * 2);
|
||||
if (ImGui.InputTextWithHint("", "Nick/Notes", ref EditUserComment, 255, ImGuiInputTextFlags.EnterReturnsTrue))
|
||||
{
|
||||
_serverManager.CurrentServer!.UidServerComments[entry.UserPair!.User.UID] = EditUserComment;
|
||||
_serverManager.Save();
|
||||
_serverManager.SetNoteForUid(entry.UserPair!.User.UID, EditUserComment);
|
||||
EditNickEntry = string.Empty;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace MareSynchronos.UI;
|
||||
public class DownloadUi : Window, IDisposable
|
||||
{
|
||||
private readonly WindowSystem _windowSystem;
|
||||
private readonly ConfigurationService _configService;
|
||||
private readonly MareConfigService _configService;
|
||||
private readonly ApiController _apiController;
|
||||
private readonly UiShared _uiShared;
|
||||
private bool _wasOpen = false;
|
||||
@@ -21,7 +21,7 @@ public class DownloadUi : Window, IDisposable
|
||||
_windowSystem.RemoveWindow(this);
|
||||
}
|
||||
|
||||
public DownloadUi(WindowSystem windowSystem, ConfigurationService configService, ApiController apiController, UiShared uiShared) : base("Mare Synchronos Downloads")
|
||||
public DownloadUi(WindowSystem windowSystem, MareConfigService configService, ApiController apiController, UiShared uiShared) : base("Mare Synchronos Downloads")
|
||||
{
|
||||
Logger.Verbose("Creating " + nameof(DownloadUi));
|
||||
_windowSystem = windowSystem;
|
||||
|
||||
@@ -16,10 +16,10 @@ public class GposeUi : WindowMediatorSubscriberBase, IDisposable
|
||||
private readonly MareCharaFileManager _mareCharaFileManager;
|
||||
private readonly DalamudUtil _dalamudUtil;
|
||||
private readonly FileDialogManager _fileDialogManager;
|
||||
private readonly ConfigurationService _configService;
|
||||
private readonly MareConfigService _configService;
|
||||
|
||||
public GposeUi(WindowSystem windowSystem, MareCharaFileManager mareCharaFileManager,
|
||||
DalamudUtil dalamudUtil, FileDialogManager fileDialogManager, ConfigurationService configService,
|
||||
DalamudUtil dalamudUtil, FileDialogManager fileDialogManager, MareConfigService configService,
|
||||
MareMediator mediator) : base(mediator, "Mare Synchronos Gpose Import UI###MareSynchronosGposeUI")
|
||||
{
|
||||
_windowSystem = windowSystem;
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace MareSynchronos.UI
|
||||
private ApiController ApiController => _uiShared.ApiController;
|
||||
private readonly PairManager _pairManager;
|
||||
private readonly ServerConfigurationManager _serverConfigurationManager;
|
||||
private readonly ConfigurationService _configService;
|
||||
private readonly MareConfigService _configService;
|
||||
private readonly Dictionary<string, bool> _showGidForEntry = new(StringComparer.Ordinal);
|
||||
private string _editGroupEntry = string.Empty;
|
||||
private string _editGroupComment = string.Empty;
|
||||
@@ -53,7 +53,7 @@ namespace MareSynchronos.UI
|
||||
private bool _modalChangePwOpened;
|
||||
private int _bulkInviteCount = 10;
|
||||
|
||||
public GroupPanel(CompactUi mainUi, UiShared uiShared, PairManager pairManager, ServerConfigurationManager serverConfigurationManager, ConfigurationService configurationService)
|
||||
public GroupPanel(CompactUi mainUi, UiShared uiShared, PairManager pairManager, ServerConfigurationManager serverConfigurationManager, MareConfigService configurationService)
|
||||
{
|
||||
_mainUi = mainUi;
|
||||
_uiShared = uiShared;
|
||||
@@ -241,13 +241,11 @@ namespace MareSynchronos.UI
|
||||
}
|
||||
|
||||
_showGidForEntry.TryGetValue(groupDto.GID, out var showGidInsteadOfName);
|
||||
if (!showGidInsteadOfName && _serverConfigurationManager.CurrentServer!.GidServerComments.TryGetValue(groupDto.GID, out var groupComment))
|
||||
var groupComment = _serverConfigurationManager.GetNoteForGid(groupDto.GID);
|
||||
if (!showGidInsteadOfName && !string.IsNullOrEmpty(groupComment))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(groupComment))
|
||||
{
|
||||
groupName = groupComment;
|
||||
textIsGid = false;
|
||||
}
|
||||
groupName = groupComment;
|
||||
textIsGid = false;
|
||||
}
|
||||
|
||||
if (!string.Equals(_editGroupEntry, groupDto.GID, StringComparison.Ordinal))
|
||||
@@ -271,9 +269,8 @@ namespace MareSynchronos.UI
|
||||
|
||||
if (ImGui.IsItemClicked(ImGuiMouseButton.Right))
|
||||
{
|
||||
_serverConfigurationManager.CurrentServer!.GidServerComments[_editGroupEntry] = _editGroupComment;
|
||||
_serverConfigurationManager.Save();
|
||||
_editGroupComment = _serverConfigurationManager.CurrentServer!.GidServerComments.TryGetValue(groupDto.GID, out string? value) ? value : string.Empty;
|
||||
_serverConfigurationManager.SetNoteForGid(_editGroupEntry, _editGroupComment);
|
||||
_editGroupComment = _serverConfigurationManager.GetNoteForGid(groupDto.GID) ?? string.Empty;
|
||||
_editGroupEntry = groupDto.GID;
|
||||
}
|
||||
}
|
||||
@@ -283,8 +280,7 @@ namespace MareSynchronos.UI
|
||||
ImGui.SetNextItemWidth(UiShared.GetWindowContentRegionWidth() - ImGui.GetCursorPosX() - buttonSizes - ImGui.GetStyle().ItemSpacing.X * 2);
|
||||
if (ImGui.InputTextWithHint("", "Comment/Notes", ref _editGroupComment, 255, ImGuiInputTextFlags.EnterReturnsTrue))
|
||||
{
|
||||
_serverConfigurationManager.CurrentServer!.GidServerComments[groupDto.GID] = _editGroupComment;
|
||||
_serverConfigurationManager.Save();
|
||||
_serverConfigurationManager.SetNoteForGid(groupDto.GID, _editGroupComment);
|
||||
_editGroupEntry = string.Empty;
|
||||
}
|
||||
|
||||
@@ -436,7 +432,7 @@ namespace MareSynchronos.UI
|
||||
.ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsPinned())
|
||||
.ThenBy(u => u.GetNote() ?? u.UserData.AliasOrUID, StringComparer.OrdinalIgnoreCase)
|
||||
.ToList();
|
||||
|
||||
|
||||
if (visibleUsers.Any())
|
||||
{
|
||||
ImGui.Text("Visible");
|
||||
@@ -820,18 +816,8 @@ namespace MareSynchronos.UI
|
||||
|
||||
var textIsUid = true;
|
||||
_mainUi.ShowUidForEntry.TryGetValue(entry.UID, out var showUidInsteadOfName);
|
||||
if (!showUidInsteadOfName && _serverConfigurationManager.CurrentServer!.UidServerComments.TryGetValue(entry.UID, out var playerText))
|
||||
{
|
||||
if (string.IsNullOrEmpty(playerText))
|
||||
{
|
||||
playerText = entryUID;
|
||||
}
|
||||
else
|
||||
{
|
||||
textIsUid = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
var playerText = _serverConfigurationManager.GetNoteForUid(entry.UID);
|
||||
if (showUidInsteadOfName || string.IsNullOrEmpty(playerText))
|
||||
{
|
||||
playerText = entryUID;
|
||||
}
|
||||
@@ -866,9 +852,8 @@ namespace MareSynchronos.UI
|
||||
|
||||
if (ImGui.IsItemClicked(ImGuiMouseButton.Right))
|
||||
{
|
||||
_serverConfigurationManager.CurrentServer!.UidServerComments[_mainUi.EditNickEntry] = _mainUi.EditUserComment;
|
||||
_serverConfigurationManager.Save();
|
||||
_mainUi.EditUserComment = _serverConfigurationManager.CurrentServer.UidServerComments.TryGetValue(entry.UID, out string? value) ? value : string.Empty;
|
||||
_serverConfigurationManager.SetNoteForUid(_mainUi.EditNickEntry, _mainUi.EditUserComment);
|
||||
_mainUi.EditUserComment = _serverConfigurationManager.GetNoteForUid(entry.UID) ?? string.Empty;
|
||||
_mainUi.EditNickEntry = entry.UID;
|
||||
}
|
||||
}
|
||||
@@ -881,8 +866,7 @@ namespace MareSynchronos.UI
|
||||
ImGui.SetNextItemWidth(UiShared.GetWindowContentRegionWidth() - ImGui.GetCursorPosX() - buttonSizes - ImGui.GetStyle().ItemSpacing.X * buttons);
|
||||
if (ImGui.InputTextWithHint("", "Nick/Notes", ref _mainUi.EditUserComment, 255, ImGuiInputTextFlags.EnterReturnsTrue))
|
||||
{
|
||||
_serverConfigurationManager.CurrentServer!.UidServerComments[entry.UID] = _mainUi.EditUserComment;
|
||||
_serverConfigurationManager.Save();
|
||||
_serverConfigurationManager.SetNoteForUid(entry.UID, _mainUi.EditUserComment);
|
||||
_mainUi.EditNickEntry = string.Empty;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using MareSynchronos.API.Dto.User;
|
||||
using MareSynchronos.Managers;
|
||||
using MareSynchronos.Models;
|
||||
|
||||
namespace MareSynchronos.UI.Handlers
|
||||
{
|
||||
@@ -17,34 +18,27 @@ namespace MareSynchronos.UI.Handlers
|
||||
|
||||
public void AddTag(string tag)
|
||||
{
|
||||
GetAvailableTagsForCurrentServer().Add(tag);
|
||||
_serverConfigurationManager.Save();
|
||||
_serverConfigurationManager.AddTag(tag);
|
||||
}
|
||||
|
||||
public void RemoveTag(string tag)
|
||||
{
|
||||
// First remove the tag from teh available pair tags
|
||||
GetAvailableTagsForCurrentServer().Remove(tag);
|
||||
// Then also clean up the tag in all the pairs
|
||||
GetUidTagDictionaryForCurrentServer().Keys
|
||||
.ToList()
|
||||
.ForEach(otherUid => RemoveTagFromPairedUid(otherUid, tag));
|
||||
_serverConfigurationManager.Save();
|
||||
_serverConfigurationManager.RemoveTag(tag);
|
||||
}
|
||||
|
||||
public void SetTagOpen(string tag, bool open)
|
||||
{
|
||||
if (open)
|
||||
{
|
||||
_serverConfigurationManager.CurrentServer!.OpenPairTags.Add(tag);
|
||||
_serverConfigurationManager.AddOpenPairTag(tag);
|
||||
}
|
||||
else
|
||||
{
|
||||
_serverConfigurationManager.CurrentServer!.OpenPairTags.Remove(tag);
|
||||
_serverConfigurationManager.RemoveOpenPairTag(tag);
|
||||
}
|
||||
_serverConfigurationManager.Save();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Is this tag opened in the paired clients UI?
|
||||
/// </summary>
|
||||
@@ -52,73 +46,39 @@ namespace MareSynchronos.UI.Handlers
|
||||
/// <returns>open true/false</returns>
|
||||
public bool IsTagOpen(string tag)
|
||||
{
|
||||
return _serverConfigurationManager.CurrentServer!.OpenPairTags.Contains(tag);
|
||||
return _serverConfigurationManager.ContainsOpenPairTag(tag);
|
||||
}
|
||||
|
||||
public List<string> GetAllTagsSorted()
|
||||
{
|
||||
return GetAvailableTagsForCurrentServer()
|
||||
return _serverConfigurationManager.GetServerAvailablePairTags()
|
||||
.OrderBy(s => s, StringComparer.OrdinalIgnoreCase)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public HashSet<string> GetOtherUidsForTag(string tag)
|
||||
{
|
||||
return GetUidTagDictionaryForCurrentServer()
|
||||
.Where(pair => pair.Value.Contains(tag, StringComparer.Ordinal))
|
||||
.Select(pair => pair.Key)
|
||||
.ToHashSet(StringComparer.Ordinal);
|
||||
return _serverConfigurationManager.GetUidsForTag(tag);
|
||||
}
|
||||
|
||||
public void AddTagToPairedUid(UserPairDto pair, string tagName)
|
||||
{
|
||||
var tagDictionary = GetUidTagDictionaryForCurrentServer();
|
||||
var tagsForPair = tagDictionary.GetValueOrDefault(pair.User.UID, new List<string>());
|
||||
tagsForPair.Add(tagName);
|
||||
tagDictionary[pair.User.UID] = tagsForPair;
|
||||
_serverConfigurationManager.Save();
|
||||
_serverConfigurationManager.AddTagForUid(pair.User.UID, tagName);
|
||||
}
|
||||
|
||||
|
||||
public void RemoveTagFromPairedUid(UserPairDto pair, string tagName)
|
||||
{
|
||||
RemoveTagFromPairedUid(pair.User.UID, tagName);
|
||||
_serverConfigurationManager.Save();
|
||||
_serverConfigurationManager.RemoveTagForUid(pair.User.UID, tagName);
|
||||
}
|
||||
|
||||
public bool HasTag(UserPairDto pair, string tagName)
|
||||
{
|
||||
var tagsForPair = GetUidTagDictionaryForCurrentServer().GetValueOrDefault(pair.User.UID, new List<string>());
|
||||
return tagsForPair.Contains(tagName, StringComparer.Ordinal);
|
||||
return _serverConfigurationManager.ContainsTag(pair.User.UID, tagName);
|
||||
}
|
||||
|
||||
public bool HasAnyTag(UserPairDto pair)
|
||||
{
|
||||
return GetUidTagDictionaryForCurrentServer().ContainsKey(pair.User.UID);
|
||||
}
|
||||
|
||||
private void RemoveTagFromPairedUid(string otherUid, string tagName)
|
||||
{
|
||||
var tagsForPair = GetUidTagDictionaryForCurrentServer().GetValueOrDefault(otherUid, new List<string>());
|
||||
tagsForPair.Remove(tagName);
|
||||
if (!tagsForPair.Any())
|
||||
{
|
||||
// No more entries in list -> we can kick out that entry completely
|
||||
GetUidTagDictionaryForCurrentServer().Remove(otherUid);
|
||||
}
|
||||
else
|
||||
{
|
||||
GetUidTagDictionaryForCurrentServer()[otherUid] = tagsForPair;
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<string, List<string>> GetUidTagDictionaryForCurrentServer()
|
||||
{
|
||||
return _serverConfigurationManager.CurrentServer!.UidServerPairedUserTags;
|
||||
}
|
||||
|
||||
private HashSet<string> GetAvailableTagsForCurrentServer()
|
||||
{
|
||||
return _serverConfigurationManager.CurrentServer!.ServerAvailablePairTags;
|
||||
return _serverConfigurationManager.HasTags(pair.User.UID);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,13 +10,14 @@ using Dalamud.Interface;
|
||||
using MareSynchronos.Managers;
|
||||
using MareSynchronos.MareConfiguration;
|
||||
using MareSynchronos.Mediator;
|
||||
using MareSynchronos.MareConfiguration.Models;
|
||||
|
||||
namespace MareSynchronos.UI;
|
||||
|
||||
internal class IntroUi : WindowMediatorSubscriberBase, IDisposable
|
||||
{
|
||||
private readonly UiShared _uiShared;
|
||||
private readonly ConfigurationService _configService;
|
||||
private readonly MareConfigService _configService;
|
||||
private readonly PeriodicFileScanner _fileCacheManager;
|
||||
private readonly ServerConfigurationManager _serverConfigurationManager;
|
||||
private readonly WindowSystem _windowSystem;
|
||||
@@ -36,7 +37,7 @@ internal class IntroUi : WindowMediatorSubscriberBase, IDisposable
|
||||
_windowSystem.RemoveWindow(this);
|
||||
}
|
||||
|
||||
public IntroUi(WindowSystem windowSystem, UiShared uiShared, ConfigurationService configService,
|
||||
public IntroUi(WindowSystem windowSystem, UiShared uiShared, MareConfigService configService,
|
||||
PeriodicFileScanner fileCacheManager, ServerConfigurationManager serverConfigurationManager, MareMediator mareMediator) : base(mareMediator, "Mare Synchronos Setup")
|
||||
{
|
||||
Logger.Verbose("Creating " + nameof(IntroUi));
|
||||
|
||||
@@ -14,12 +14,13 @@ using MareSynchronos.Managers;
|
||||
using MareSynchronos.API.Data.Comparer;
|
||||
using MareSynchronos.MareConfiguration;
|
||||
using MareSynchronos.Mediator;
|
||||
using MareSynchronos.MareConfiguration.Models;
|
||||
|
||||
namespace MareSynchronos.UI;
|
||||
|
||||
public class SettingsUi : WindowMediatorSubscriberBase, IDisposable
|
||||
{
|
||||
private readonly ConfigurationService _configService;
|
||||
private readonly MareConfigService _configService;
|
||||
private readonly WindowSystem _windowSystem;
|
||||
private ApiController ApiController => _uiShared.ApiController;
|
||||
private readonly MareCharaFileManager _mareCharaFileManager;
|
||||
@@ -34,7 +35,7 @@ public class SettingsUi : WindowMediatorSubscriberBase, IDisposable
|
||||
private bool _wasOpen = false;
|
||||
|
||||
public SettingsUi(WindowSystem windowSystem,
|
||||
UiShared uiShared, ConfigurationService configService,
|
||||
UiShared uiShared, MareConfigService configService,
|
||||
MareCharaFileManager mareCharaFileManager, PairManager pairManager,
|
||||
ServerConfigurationManager serverConfigurationManager, MareMediator mediator) : base(mediator, "Mare Synchronos Settings")
|
||||
{
|
||||
|
||||
@@ -13,6 +13,7 @@ using MareSynchronos.FileCache;
|
||||
using MareSynchronos.Localization;
|
||||
using MareSynchronos.Managers;
|
||||
using MareSynchronos.MareConfiguration;
|
||||
using MareSynchronos.MareConfiguration.Models;
|
||||
using MareSynchronos.Models;
|
||||
using MareSynchronos.Utils;
|
||||
using MareSynchronos.WebAPI;
|
||||
@@ -28,7 +29,7 @@ public partial class UiShared : IDisposable
|
||||
private readonly ApiController _apiController;
|
||||
private readonly PeriodicFileScanner _cacheScanner;
|
||||
public readonly FileDialogManager FileDialogManager;
|
||||
private readonly ConfigurationService _configService;
|
||||
private readonly MareConfigService _configService;
|
||||
private readonly DalamudUtil _dalamudUtil;
|
||||
private readonly DalamudPluginInterface _pluginInterface;
|
||||
private readonly Dalamud.Localization _localization;
|
||||
@@ -53,7 +54,7 @@ public partial class UiShared : IDisposable
|
||||
public ApiController ApiController => _apiController;
|
||||
|
||||
public UiShared(IpcManager ipcManager, ApiController apiController, PeriodicFileScanner cacheScanner, FileDialogManager fileDialogManager,
|
||||
ConfigurationService configService, DalamudUtil dalamudUtil, DalamudPluginInterface pluginInterface, Dalamud.Localization localization,
|
||||
MareConfigService configService, DalamudUtil dalamudUtil, DalamudPluginInterface pluginInterface, Dalamud.Localization localization,
|
||||
ServerConfigurationManager serverManager)
|
||||
{
|
||||
_ipcManager = ipcManager;
|
||||
@@ -631,8 +632,6 @@ public partial class UiShared : IDisposable
|
||||
|
||||
splitNotes.RemoveAll(n => string.Equals(n, _notesStart) || string.Equals(n, _notesEnd));
|
||||
|
||||
var comments = _serverConfigurationManager.CurrentServer!.UidServerComments;
|
||||
|
||||
foreach (var note in splitNotes)
|
||||
{
|
||||
try
|
||||
@@ -640,8 +639,8 @@ public partial class UiShared : IDisposable
|
||||
var splittedEntry = note.Split(":", 2, StringSplitOptions.RemoveEmptyEntries);
|
||||
var uid = splittedEntry[0];
|
||||
var comment = splittedEntry[1].Trim('"');
|
||||
if (comments.ContainsKey(uid) && !overwrite) continue;
|
||||
_serverConfigurationManager.CurrentServer.UidServerComments[uid] = comment;
|
||||
if (_serverConfigurationManager.GetNoteForUid(uid) != null && !overwrite) continue;
|
||||
_serverConfigurationManager.SetNoteForUid(uid, comment);
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -649,7 +648,7 @@ public partial class UiShared : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
_serverConfigurationManager.Save();
|
||||
_serverConfigurationManager.SaveNotes();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user