Merge branch '1.12.3' into patch-notes
This commit is contained in:
@@ -138,7 +138,7 @@ public sealed class PairManager : DisposableMediatorSubscriberBase
|
||||
{
|
||||
if (_allClientPairs.TryGetValue(user, out var pair))
|
||||
{
|
||||
Mediator.Publish(new ClearProfileDataMessage(pair.UserData));
|
||||
Mediator.Publish(new ClearProfileUserDataMessage(pair.UserData));
|
||||
pair.MarkOffline();
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ public sealed class PairManager : DisposableMediatorSubscriberBase
|
||||
{
|
||||
if (!_allClientPairs.ContainsKey(dto.User)) throw new InvalidOperationException("No user found for " + dto);
|
||||
|
||||
Mediator.Publish(new ClearProfileDataMessage(dto.User));
|
||||
Mediator.Publish(new ClearProfileUserDataMessage(dto.User));
|
||||
|
||||
var pair = _allClientPairs[dto.User];
|
||||
if (pair.HasCachedPlayer)
|
||||
@@ -254,7 +254,7 @@ public sealed class PairManager : DisposableMediatorSubscriberBase
|
||||
|
||||
if (pair.UserPair.OtherPermissions.IsPaused() != dto.Permissions.IsPaused())
|
||||
{
|
||||
Mediator.Publish(new ClearProfileDataMessage(dto.User));
|
||||
Mediator.Publish(new ClearProfileUserDataMessage(dto.User));
|
||||
}
|
||||
|
||||
pair.UserPair.OtherPermissions = dto.Permissions;
|
||||
@@ -280,7 +280,7 @@ public sealed class PairManager : DisposableMediatorSubscriberBase
|
||||
|
||||
if (pair.UserPair.OwnPermissions.IsPaused() != dto.Permissions.IsPaused())
|
||||
{
|
||||
Mediator.Publish(new ClearProfileDataMessage(dto.User));
|
||||
Mediator.Publish(new ClearProfileUserDataMessage(dto.User));
|
||||
}
|
||||
|
||||
pair.UserPair.OwnPermissions = dto.Permissions;
|
||||
|
||||
6
LightlessSync/Services/LightlessGroupProfileData.cs
Normal file
6
LightlessSync/Services/LightlessGroupProfileData.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace LightlessSync.Services;
|
||||
|
||||
public record LightlessGroupProfileData(string Base64ProfilePicture, string Description, int[] Tags, bool IsNsfw, bool IsDisabled)
|
||||
{
|
||||
public Lazy<byte[]> ImageData { get; } = new Lazy<byte[]>(Convert.FromBase64String(Base64ProfilePicture));
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -1,6 +1,6 @@
|
||||
namespace LightlessSync.Services;
|
||||
|
||||
public record LightlessProfileData(bool IsFlagged, bool IsNSFW, string Base64ProfilePicture, string Base64SupporterPicture, string Description)
|
||||
public record LightlessUserProfileData(bool IsFlagged, bool IsNSFW, string Base64ProfilePicture, string Base64SupporterPicture, string Description)
|
||||
{
|
||||
public Lazy<byte[]> ImageData { get; } = new Lazy<byte[]>(Convert.FromBase64String(Base64ProfilePicture));
|
||||
public Lazy<byte[]> SupporterImageData { get; } = new Lazy<byte[]>(string.IsNullOrEmpty(Base64SupporterPicture) ? [] : Convert.FromBase64String(Base64SupporterPicture));
|
||||
@@ -70,7 +70,8 @@ public record DownloadStartedMessage(GameObjectHandler DownloadId, Dictionary<st
|
||||
public record DownloadFinishedMessage(GameObjectHandler DownloadId) : MessageBase;
|
||||
public record UiToggleMessage(Type UiType) : MessageBase;
|
||||
public record PlayerUploadingMessage(GameObjectHandler Handler, bool IsUploading) : MessageBase;
|
||||
public record ClearProfileDataMessage(UserData? UserData = null) : MessageBase;
|
||||
public record ClearProfileUserDataMessage(UserData? UserData = null) : MessageBase;
|
||||
public record ClearProfileGroupDataMessage(GroupData? GroupData = null) : MessageBase;
|
||||
public record CyclePauseMessage(UserData UserData) : MessageBase;
|
||||
public record PauseMessage(UserData UserData) : MessageBase;
|
||||
public record ProfilePopoutToggle(Pair? Pair) : MessageBase;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using LightlessSync.API.Dto.Group;
|
||||
using Dalamud.Interface.ImGuiFileDialog;
|
||||
using LightlessSync.API.Dto.Group;
|
||||
using LightlessSync.PlayerData.Pairs;
|
||||
using LightlessSync.Services.Mediator;
|
||||
using LightlessSync.Services.ServerConfiguration;
|
||||
@@ -18,10 +19,11 @@ public class UiFactory
|
||||
private readonly ServerConfigurationManager _serverConfigManager;
|
||||
private readonly LightlessProfileManager _lightlessProfileManager;
|
||||
private readonly PerformanceCollectorService _performanceCollectorService;
|
||||
private readonly FileDialogManager _fileDialogManager;
|
||||
|
||||
public UiFactory(ILoggerFactory loggerFactory, LightlessMediator lightlessMediator, ApiController apiController,
|
||||
UiSharedService uiSharedService, PairManager pairManager, ServerConfigurationManager serverConfigManager,
|
||||
LightlessProfileManager lightlessProfileManager, PerformanceCollectorService performanceCollectorService)
|
||||
LightlessProfileManager lightlessProfileManager, PerformanceCollectorService performanceCollectorService, FileDialogManager fileDialogManager)
|
||||
{
|
||||
_loggerFactory = loggerFactory;
|
||||
_lightlessMediator = lightlessMediator;
|
||||
@@ -31,12 +33,13 @@ public class UiFactory
|
||||
_serverConfigManager = serverConfigManager;
|
||||
_lightlessProfileManager = lightlessProfileManager;
|
||||
_performanceCollectorService = performanceCollectorService;
|
||||
_fileDialogManager = fileDialogManager;
|
||||
}
|
||||
|
||||
public SyncshellAdminUI CreateSyncshellAdminUi(GroupFullInfoDto dto)
|
||||
{
|
||||
return new SyncshellAdminUI(_loggerFactory.CreateLogger<SyncshellAdminUI>(), _lightlessMediator,
|
||||
_apiController, _uiSharedService, _pairManager, dto, _performanceCollectorService);
|
||||
_apiController, _uiSharedService, _pairManager, dto, _performanceCollectorService, _lightlessProfileManager, _fileDialogManager);
|
||||
}
|
||||
|
||||
public StandaloneProfileUi CreateStandaloneProfileUi(Pair pair)
|
||||
|
||||
@@ -63,7 +63,7 @@ public class EditProfileUi : WindowMediatorSubscriberBase
|
||||
Mediator.Subscribe<GposeStartMessage>(this, (_) => { _wasOpen = IsOpen; IsOpen = false; });
|
||||
Mediator.Subscribe<GposeEndMessage>(this, (_) => IsOpen = _wasOpen);
|
||||
Mediator.Subscribe<DisconnectedMessage>(this, (_) => IsOpen = false);
|
||||
Mediator.Subscribe<ClearProfileDataMessage>(this, (msg) =>
|
||||
Mediator.Subscribe<ClearProfileUserDataMessage>(this, (msg) =>
|
||||
{
|
||||
if (msg.UserData == null || string.Equals(msg.UserData.UID, _apiController.UID, StringComparison.Ordinal))
|
||||
{
|
||||
@@ -91,6 +91,7 @@ public class EditProfileUi : WindowMediatorSubscriberBase
|
||||
|
||||
protected override void DrawInternal()
|
||||
{
|
||||
|
||||
_uiSharedService.UnderlinedBigText("Notes and Rules for Profiles", UIColors.Get("LightlessYellow"));
|
||||
ImGui.Dummy(new Vector2(5));
|
||||
|
||||
@@ -108,7 +109,8 @@ public class EditProfileUi : WindowMediatorSubscriberBase
|
||||
|
||||
ImGui.Dummy(new Vector2(3));
|
||||
|
||||
var profile = _lightlessProfileManager.GetLightlessProfile(new UserData(_apiController.UID));
|
||||
var profile = _lightlessProfileManager.GetLightlessUserProfile(new UserData(_apiController.UID));
|
||||
_logger.LogInformation("Profile fetched for drawing: {profile}", profile);
|
||||
|
||||
if (ImGui.BeginTabBar("##EditProfileTabs"))
|
||||
{
|
||||
@@ -204,7 +206,7 @@ public class EditProfileUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
|
||||
_showFileDialogError = false;
|
||||
await _apiController.UserSetProfile(new UserProfileDto(new UserData(_apiController.UID), Disabled: false, IsNSFW: null, Convert.ToBase64String(fileContent), Description: null))
|
||||
await _apiController.UserSetProfile(new UserProfileDto(new UserData(_apiController.UID), Disabled: false, IsNSFW: null, Convert.ToBase64String(fileContent), Description: null, Tags: null))
|
||||
.ConfigureAwait(false);
|
||||
});
|
||||
});
|
||||
@@ -213,7 +215,7 @@ public class EditProfileUi : WindowMediatorSubscriberBase
|
||||
ImGui.SameLine();
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Trash, "Clear uploaded profile picture"))
|
||||
{
|
||||
_ = _apiController.UserSetProfile(new UserProfileDto(new UserData(_apiController.UID), Disabled: false, IsNSFW: null, "", Description: null));
|
||||
_ = _apiController.UserSetProfile(new UserProfileDto(new UserData(_apiController.UID), Disabled: false, IsNSFW: null, "", Description: null, Tags: null));
|
||||
}
|
||||
UiSharedService.AttachToolTip("Clear your currently uploaded profile picture");
|
||||
if (_showFileDialogError)
|
||||
@@ -223,7 +225,7 @@ public class EditProfileUi : WindowMediatorSubscriberBase
|
||||
var isNsfw = profile.IsNSFW;
|
||||
if (ImGui.Checkbox("Profile is NSFW", ref isNsfw))
|
||||
{
|
||||
_ = _apiController.UserSetProfile(new UserProfileDto(new UserData(_apiController.UID), Disabled: false, isNsfw, ProfilePictureBase64: null, Description: null));
|
||||
_ = _apiController.UserSetProfile(new UserProfileDto(new UserData(_apiController.UID), Disabled: false, isNsfw, ProfilePictureBase64: null, Description: null, Tags: null));
|
||||
}
|
||||
_uiSharedService.DrawHelpText("If your profile description or image can be considered NSFW, toggle this to ON");
|
||||
var widthTextBox = 400;
|
||||
@@ -262,13 +264,13 @@ public class EditProfileUi : WindowMediatorSubscriberBase
|
||||
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Save, "Save Description"))
|
||||
{
|
||||
_ = _apiController.UserSetProfile(new UserProfileDto(new UserData(_apiController.UID), Disabled: false, IsNSFW: null, ProfilePictureBase64: null, _descriptionText));
|
||||
_ = _apiController.UserSetProfile(new UserProfileDto(new UserData(_apiController.UID), Disabled: false, IsNSFW: null, ProfilePictureBase64: null, _descriptionText, Tags: null));
|
||||
}
|
||||
UiSharedService.AttachToolTip("Sets your profile description text");
|
||||
ImGui.SameLine();
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Trash, "Clear Description"))
|
||||
{
|
||||
_ = _apiController.UserSetProfile(new UserProfileDto(new UserData(_apiController.UID), Disabled: false, IsNSFW: null, ProfilePictureBase64: null, ""));
|
||||
_ = _apiController.UserSetProfile(new UserProfileDto(new UserData(_apiController.UID), Disabled: false, IsNSFW: null, ProfilePictureBase64: null, "", Tags: null));
|
||||
}
|
||||
UiSharedService.AttachToolTip("Clears your profile description text");
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ public class PopoutProfileUi : WindowMediatorSubscriberBase
|
||||
{
|
||||
var spacing = ImGui.GetStyle().ItemSpacing;
|
||||
|
||||
var lightlessProfile = _lightlessProfileManager.GetLightlessProfile(_pair.UserData);
|
||||
var lightlessProfile = _lightlessProfileManager.GetLightlessUserProfile(_pair.UserData);
|
||||
|
||||
if (_textureWrap == null || !lightlessProfile.ImageData.Value.SequenceEqual(_lastProfilePicture))
|
||||
{
|
||||
|
||||
12
LightlessSync/UI/ProfileTags.cs
Normal file
12
LightlessSync/UI/ProfileTags.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
namespace LightlessSync.UI
|
||||
{
|
||||
public enum ProfileTags
|
||||
{
|
||||
SFW = 0,
|
||||
NSFW = 1,
|
||||
RP = 2,
|
||||
ERP = 3,
|
||||
Venues = 4,
|
||||
Gpose = 5
|
||||
}
|
||||
}
|
||||
@@ -2302,7 +2302,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
{
|
||||
if (ImGui.Checkbox("Show Lightless Profiles on Hover", ref showProfiles))
|
||||
{
|
||||
Mediator.Publish(new ClearProfileDataMessage());
|
||||
Mediator.Publish(new ClearProfileUserDataMessage());
|
||||
_configService.Current.ProfilesShow = showProfiles;
|
||||
_configService.Save();
|
||||
}
|
||||
@@ -2329,7 +2329,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
ImGui.Unindent();
|
||||
if (ImGui.Checkbox("Show profiles marked as NSFW", ref showNsfwProfiles))
|
||||
{
|
||||
Mediator.Publish(new ClearProfileDataMessage());
|
||||
Mediator.Publish(new ClearProfileUserDataMessage());
|
||||
_configService.Current.ProfilesAllowNsfw = showNsfwProfiles;
|
||||
_configService.Save();
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ public class StandaloneProfileUi : WindowMediatorSubscriberBase
|
||||
{
|
||||
var spacing = ImGui.GetStyle().ItemSpacing;
|
||||
|
||||
var lightlessProfile = _lightlessProfileManager.GetLightlessProfile(Pair.UserData);
|
||||
var lightlessProfile = _lightlessProfileManager.GetLightlessUserProfile(Pair.UserData);
|
||||
|
||||
if (_textureWrap == null || !lightlessProfile.ImageData.Value.SequenceEqual(_lastProfilePicture))
|
||||
{
|
||||
|
||||
@@ -1,17 +1,26 @@
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Colors;
|
||||
using Dalamud.Interface.ImGuiFileDialog;
|
||||
using Dalamud.Interface.Textures.TextureWraps;
|
||||
using Dalamud.Interface.Utility;
|
||||
using Dalamud.Interface.Utility.Raii;
|
||||
using LightlessSync.API.Data;
|
||||
using LightlessSync.API.Data.Enum;
|
||||
using LightlessSync.API.Data.Extensions;
|
||||
using LightlessSync.API.Dto.Group;
|
||||
using LightlessSync.API.Dto.User;
|
||||
using LightlessSync.PlayerData.Pairs;
|
||||
using LightlessSync.Services;
|
||||
using LightlessSync.Services.Mediator;
|
||||
using LightlessSync.UI.Handlers;
|
||||
using LightlessSync.WebAPI;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
namespace LightlessSync.UI;
|
||||
|
||||
@@ -22,29 +31,51 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
||||
private readonly bool _isOwner = false;
|
||||
private readonly List<string> _oneTimeInvites = [];
|
||||
private readonly PairManager _pairManager;
|
||||
private readonly LightlessProfileManager _lightlessProfileManager;
|
||||
private readonly FileDialogManager _fileDialogManager;
|
||||
private readonly UiSharedService _uiSharedService;
|
||||
private List<BannedGroupUserDto> _bannedUsers = [];
|
||||
private LightlessGroupProfileData? _profileData = null;
|
||||
private bool _adjustedForScollBarsLocalProfile = false;
|
||||
private bool _adjustedForScollBarsOnlineProfile = false;
|
||||
private string _descriptionText = string.Empty;
|
||||
private IDalamudTextureWrap? _pfpTextureWrap;
|
||||
private string _profileDescription = string.Empty;
|
||||
private byte[] _profileImage = [];
|
||||
private bool _showFileDialogError = false;
|
||||
private int _multiInvites;
|
||||
private string _newPassword;
|
||||
private bool _pwChangeSuccess;
|
||||
private Task<int>? _pruneTestTask;
|
||||
private Task<int>? _pruneTask;
|
||||
private int _pruneDays = 14;
|
||||
private List<int> _selectedTags = [];
|
||||
|
||||
public SyncshellAdminUI(ILogger<SyncshellAdminUI> logger, LightlessMediator mediator, ApiController apiController,
|
||||
UiSharedService uiSharedService, PairManager pairManager, GroupFullInfoDto groupFullInfo, PerformanceCollectorService performanceCollectorService)
|
||||
UiSharedService uiSharedService, PairManager pairManager, GroupFullInfoDto groupFullInfo, PerformanceCollectorService performanceCollectorService, LightlessProfileManager lightlessProfileManager, FileDialogManager fileDialogManager)
|
||||
: base(logger, mediator, "Syncshell Admin Panel (" + groupFullInfo.GroupAliasOrGID + ")", performanceCollectorService)
|
||||
{
|
||||
GroupFullInfo = groupFullInfo;
|
||||
_apiController = apiController;
|
||||
_uiSharedService = uiSharedService;
|
||||
_pairManager = pairManager;
|
||||
_lightlessProfileManager = lightlessProfileManager;
|
||||
_fileDialogManager = fileDialogManager;
|
||||
|
||||
_isOwner = string.Equals(GroupFullInfo.OwnerUID, _apiController.UID, StringComparison.Ordinal);
|
||||
_isModerator = GroupFullInfo.GroupUserInfo.IsModerator();
|
||||
_newPassword = string.Empty;
|
||||
_multiInvites = 30;
|
||||
_pwChangeSuccess = true;
|
||||
IsOpen = true;
|
||||
Mediator.Subscribe<ClearProfileGroupDataMessage>(this, (msg) =>
|
||||
{
|
||||
if (msg.GroupData == null || string.Equals(msg.GroupData.AliasOrGID, GroupFullInfo.Group.AliasOrGID, StringComparison.Ordinal))
|
||||
{
|
||||
_pfpTextureWrap?.Dispose();
|
||||
_pfpTextureWrap = null;
|
||||
}
|
||||
});
|
||||
SizeConstraints = new WindowSizeConstraints()
|
||||
{
|
||||
MinimumSize = new(700, 500),
|
||||
@@ -58,10 +89,13 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
||||
{
|
||||
if (!_isModerator && !_isOwner) return;
|
||||
|
||||
_logger.LogTrace("Drawing Syncshell Admin UI for {group}", GroupFullInfo.GroupAliasOrGID);
|
||||
GroupFullInfo = _pairManager.Groups[GroupFullInfo.Group];
|
||||
|
||||
using var id = ImRaii.PushId("syncshell_admin_" + GroupFullInfo.GID);
|
||||
_profileData = _lightlessProfileManager.GetLightlessGroupProfile(GroupFullInfo.Group);
|
||||
GetTagsFromProfile();
|
||||
|
||||
using var id = ImRaii.PushId("syncshell_admin_" + GroupFullInfo.GID);
|
||||
using (_uiSharedService.UidFont.Push())
|
||||
_uiSharedService.UnderlinedBigText(GroupFullInfo.GroupAliasOrGID + " Administrative Panel", UIColors.Get("LightlessBlue"));
|
||||
|
||||
@@ -69,14 +103,16 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
||||
var perm = GroupFullInfo.GroupPermissions;
|
||||
|
||||
using var tabbar = ImRaii.TabBar("syncshell_tab_" + GroupFullInfo.GID);
|
||||
|
||||
|
||||
if (tabbar)
|
||||
{
|
||||
DrawInvites(perm);
|
||||
|
||||
DrawManagement();
|
||||
|
||||
DrawPermission(perm);
|
||||
DrawPermission(perm);
|
||||
|
||||
DrawProfile();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,6 +212,184 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
||||
ownerTab.Dispose();
|
||||
}
|
||||
}
|
||||
private void DrawProfile()
|
||||
{
|
||||
var profileTab = ImRaii.TabItem("Profile");
|
||||
|
||||
if (profileTab)
|
||||
{
|
||||
if (_uiSharedService.MediumTreeNode("Current Profile", UIColors.Get("LightlessPurple")))
|
||||
{
|
||||
ImGui.Dummy(new Vector2(5));
|
||||
|
||||
if (!_profileImage.SequenceEqual(_profileData.ImageData.Value))
|
||||
{
|
||||
_profileImage = _profileData.ImageData.Value;
|
||||
_pfpTextureWrap?.Dispose();
|
||||
_pfpTextureWrap = _uiSharedService.LoadImage(_profileImage);
|
||||
}
|
||||
|
||||
if (!string.Equals(_profileDescription, _profileData.Description, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_profileDescription = _profileData.Description;
|
||||
_descriptionText = _profileDescription;
|
||||
}
|
||||
|
||||
if (_pfpTextureWrap != null)
|
||||
{
|
||||
ImGui.Image(_pfpTextureWrap.Handle, ImGuiHelpers.ScaledVector2(_pfpTextureWrap.Width, _pfpTextureWrap.Height));
|
||||
}
|
||||
|
||||
var spacing = ImGui.GetStyle().ItemSpacing.X;
|
||||
ImGuiHelpers.ScaledRelativeSameLine(256, spacing);
|
||||
using (_uiSharedService.GameFont.Push())
|
||||
{
|
||||
var descriptionTextSize = ImGui.CalcTextSize(_profileData.Description, wrapWidth: 256f);
|
||||
var childFrame = ImGuiHelpers.ScaledVector2(256 + ImGui.GetStyle().WindowPadding.X + ImGui.GetStyle().WindowBorderSize, 256);
|
||||
if (descriptionTextSize.Y > childFrame.Y)
|
||||
{
|
||||
_adjustedForScollBarsOnlineProfile = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_adjustedForScollBarsOnlineProfile = false;
|
||||
}
|
||||
childFrame = childFrame with
|
||||
{
|
||||
X = childFrame.X + (_adjustedForScollBarsOnlineProfile ? ImGui.GetStyle().ScrollbarSize : 0),
|
||||
};
|
||||
if (ImGui.BeginChildFrame(101, childFrame))
|
||||
{
|
||||
UiSharedService.TextWrapped(_profileData.Description);
|
||||
}
|
||||
ImGui.EndChildFrame();
|
||||
ImGui.TreePop();
|
||||
}
|
||||
var nsfw = _profileData.IsNsfw;
|
||||
ImGui.BeginDisabled();
|
||||
ImGui.Checkbox("Is NSFW", ref nsfw);
|
||||
ImGui.EndDisabled();
|
||||
}
|
||||
|
||||
ImGui.Separator();
|
||||
|
||||
if (_uiSharedService.MediumTreeNode("Profile Settings", UIColors.Get("LightlessPurple")))
|
||||
{
|
||||
ImGui.Dummy(new Vector2(5));
|
||||
ImGui.TextUnformatted($"Profile Picture:");
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.FileUpload, "Upload new profile picture"))
|
||||
{
|
||||
_fileDialogManager.OpenFileDialog("Select new Profile picture", ".png", (success, file) =>
|
||||
{
|
||||
if (!success) return;
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
var fileContent = await File.ReadAllBytesAsync(file).ConfigureAwait(false);
|
||||
MemoryStream ms = new(fileContent);
|
||||
await using (ms.ConfigureAwait(false))
|
||||
{
|
||||
var format = await Image.DetectFormatAsync(ms).ConfigureAwait(false);
|
||||
if (!format.FileExtensions.Contains("png", StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
_showFileDialogError = true;
|
||||
return;
|
||||
}
|
||||
using var image = Image.Load<Rgba32>(fileContent);
|
||||
|
||||
if (image.Width > 512 || image.Height > 512 || (fileContent.Length > 2000 * 1024))
|
||||
{
|
||||
_showFileDialogError = true;
|
||||
return;
|
||||
}
|
||||
|
||||
_showFileDialogError = false;
|
||||
await _apiController.GroupSetProfile(new GroupProfileDto(new GroupData(GroupFullInfo.Group.AliasOrGID), Description: null, Tags: null, Convert.ToBase64String(fileContent), IsNsfw: null, IsDisabled: null))
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
UiSharedService.AttachToolTip("Select and upload a new profile picture");
|
||||
ImGui.SameLine();
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Trash, "Clear uploaded profile picture"))
|
||||
{
|
||||
_ = _apiController.GroupSetProfile(new GroupProfileDto(new GroupData(GroupFullInfo.Group.AliasOrGID), Description: null, Tags: null, PictureBase64: null, IsNsfw: null, IsDisabled: null));
|
||||
}
|
||||
UiSharedService.AttachToolTip("Clear your currently uploaded profile picture");
|
||||
if (_showFileDialogError)
|
||||
{
|
||||
UiSharedService.ColorTextWrapped("The profile picture must be a PNG file with a maximum height and width of 256px and 250KiB size", ImGuiColors.DalamudRed);
|
||||
}
|
||||
ImGui.Separator();
|
||||
ImGui.TextUnformatted($"Tags:");
|
||||
var childFrameLocal = ImGuiHelpers.ScaledVector2(256 + ImGui.GetStyle().WindowPadding.X + ImGui.GetStyle().WindowBorderSize, 200);
|
||||
|
||||
var allCategoryIndexes = Enum.GetValues<ProfileTags>()
|
||||
.Cast<int>()
|
||||
.ToList();
|
||||
|
||||
foreach(int tag in allCategoryIndexes)
|
||||
{
|
||||
using (ImRaii.PushId($"tag-{tag}")) DrawTag(tag);
|
||||
}
|
||||
ImGui.Separator();
|
||||
var widthTextBox = 400;
|
||||
var posX = ImGui.GetCursorPosX();
|
||||
ImGui.TextUnformatted($"Description {_descriptionText.Length}/1500");
|
||||
ImGui.SetCursorPosX(posX);
|
||||
ImGuiHelpers.ScaledRelativeSameLine(widthTextBox, ImGui.GetStyle().ItemSpacing.X);
|
||||
ImGui.TextUnformatted("Preview (approximate)");
|
||||
using (_uiSharedService.GameFont.Push())
|
||||
ImGui.InputTextMultiline("##description", ref _descriptionText, 1500, ImGuiHelpers.ScaledVector2(widthTextBox, 200));
|
||||
|
||||
ImGui.SameLine();
|
||||
|
||||
using (_uiSharedService.GameFont.Push())
|
||||
{
|
||||
var descriptionTextSizeLocal = ImGui.CalcTextSize(_descriptionText, wrapWidth: 256f);
|
||||
if (descriptionTextSizeLocal.Y > childFrameLocal.Y)
|
||||
{
|
||||
_adjustedForScollBarsLocalProfile = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_adjustedForScollBarsLocalProfile = false;
|
||||
}
|
||||
childFrameLocal = childFrameLocal with
|
||||
{
|
||||
X = childFrameLocal.X + (_adjustedForScollBarsLocalProfile ? ImGui.GetStyle().ScrollbarSize : 0),
|
||||
};
|
||||
if (ImGui.BeginChildFrame(102, childFrameLocal))
|
||||
{
|
||||
UiSharedService.TextWrapped(_descriptionText);
|
||||
}
|
||||
ImGui.EndChildFrame();
|
||||
}
|
||||
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Save, "Save Description"))
|
||||
{
|
||||
_ = _apiController.GroupSetProfile(new GroupProfileDto(new GroupData(GroupFullInfo.Group.AliasOrGID), Description: _descriptionText, Tags: null, PictureBase64: null, IsNsfw: null, IsDisabled: null));
|
||||
}
|
||||
UiSharedService.AttachToolTip("Sets your profile description text");
|
||||
ImGui.SameLine();
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Trash, "Clear Description"))
|
||||
{
|
||||
_ = _apiController.GroupSetProfile(new GroupProfileDto(new GroupData(GroupFullInfo.Group.AliasOrGID), Description: null, Tags: null, PictureBase64: null, IsNsfw: null, IsDisabled: null));
|
||||
}
|
||||
UiSharedService.AttachToolTip("Clears your profile description text");
|
||||
ImGui.Separator();
|
||||
ImGui.TextUnformatted($"Profile Options:");
|
||||
var isNsfw = _profileData.IsNsfw;
|
||||
if (ImGui.Checkbox("Profile is NSFW", ref isNsfw))
|
||||
{
|
||||
_ = _apiController.GroupSetProfile(new GroupProfileDto(new GroupData(GroupFullInfo.Group.AliasOrGID), Description: null, Tags: null, PictureBase64: null, IsNsfw: isNsfw, IsDisabled: null));
|
||||
}
|
||||
_uiSharedService.DrawHelpText("If your profile description or image can be considered NSFW, toggle this to ON");
|
||||
ImGui.TreePop();
|
||||
}
|
||||
}
|
||||
profileTab.Dispose();
|
||||
}
|
||||
|
||||
private void DrawManagement()
|
||||
{
|
||||
@@ -192,7 +406,7 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
||||
{
|
||||
var tableFlags = ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingStretchProp;
|
||||
if (pairs.Count > 10) tableFlags |= ImGuiTableFlags.ScrollY;
|
||||
using var table = ImRaii.Table("userList#" + GroupFullInfo.Group.GID, 3, tableFlags);
|
||||
using var table = ImRaii.Table("userList#" + GroupFullInfo.Group.AliasOrGID, 3, tableFlags);
|
||||
if (table)
|
||||
{
|
||||
ImGui.TableSetupColumn("Alias/UID/Note", ImGuiTableColumnFlags.None, 4);
|
||||
@@ -474,7 +688,6 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
||||
ImGui.Separator();
|
||||
}
|
||||
mgmtTab.Dispose();
|
||||
|
||||
}
|
||||
|
||||
private void DrawInvites(GroupPermissions perm)
|
||||
@@ -521,9 +734,37 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
||||
}
|
||||
inviteTab.Dispose();
|
||||
}
|
||||
private void DrawTag(int tag)
|
||||
{
|
||||
var HasTag = _selectedTags.Contains(tag);
|
||||
var tagName = (ProfileTags)tag;
|
||||
|
||||
if (ImGui.Checkbox(tagName.ToString(), ref HasTag))
|
||||
{
|
||||
if (HasTag)
|
||||
{
|
||||
_selectedTags.Add(tag);
|
||||
_ = _apiController.GroupSetProfile(new GroupProfileDto(new GroupData(GroupFullInfo.Group.AliasOrGID), Description: null, Tags: _selectedTags.ToArray(), PictureBase64: null, IsNsfw: null, IsDisabled: null));
|
||||
}
|
||||
else
|
||||
{
|
||||
_selectedTags.Remove(tag);
|
||||
_ = _apiController.GroupSetProfile(new GroupProfileDto(new GroupData(GroupFullInfo.Group.AliasOrGID), Description: null, Tags: _selectedTags.ToArray(), PictureBase64: null, IsNsfw: null, IsDisabled: null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void GetTagsFromProfile()
|
||||
{
|
||||
if (_profileData != null)
|
||||
{
|
||||
_selectedTags = [.. _profileData.Tags];
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnClose()
|
||||
{
|
||||
Mediator.Publish(new RemoveWindowMessage(this));
|
||||
_pfpTextureWrap?.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -84,7 +84,7 @@ public partial class ApiController
|
||||
|
||||
public async Task<UserProfileDto> UserGetProfile(UserDto dto)
|
||||
{
|
||||
if (!IsConnected) return new UserProfileDto(dto.User, Disabled: false, IsNSFW: null, ProfilePictureBase64: null, Description: null);
|
||||
if (!IsConnected) return new UserProfileDto(dto.User, Disabled: false, IsNSFW: null, ProfilePictureBase64: null, Description: null, Tags: null);
|
||||
return await _lightlessHub!.InvokeAsync<UserProfileDto>(nameof(UserGetProfile), dto).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -195,7 +195,14 @@ public partial class ApiController
|
||||
public Task Client_UserUpdateProfile(UserDto dto)
|
||||
{
|
||||
Logger.LogDebug("Client_UserUpdateProfile: {dto}", dto);
|
||||
ExecuteSafely(() => Mediator.Publish(new ClearProfileDataMessage(dto.User)));
|
||||
ExecuteSafely(() => Mediator.Publish(new ClearProfileUserDataMessage(dto.User)));
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task Client_GroupSendProfile(GroupProfileDto groupInfo)
|
||||
{
|
||||
Logger.LogDebug("Client_GroupSendProfile: {dto}", groupInfo);
|
||||
ExecuteSafely(() => Mediator.Publish(new ClearProfileGroupDataMessage(groupInfo.Group)));
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
@@ -380,6 +387,12 @@ public partial class ApiController
|
||||
_lightlessHub!.On(nameof(Client_UserUpdateProfile), act);
|
||||
}
|
||||
|
||||
public void ClientGroupSendProfile(Action<GroupProfileDto> act)
|
||||
{
|
||||
if (_initialized) return;
|
||||
_lightlessHub!.On(nameof(Client_GroupSendProfile), act);
|
||||
}
|
||||
|
||||
public void OnUserUpdateSelfPairPermissions(Action<UserPermissionsDto> act)
|
||||
{
|
||||
if (_initialized) return;
|
||||
|
||||
@@ -115,6 +115,18 @@ public partial class ApiController
|
||||
CheckConnection();
|
||||
return await _lightlessHub!.InvokeAsync<int>(nameof(GroupPrune), group, days, execute).ConfigureAwait(false);
|
||||
}
|
||||
public async Task<GroupProfileDto> GroupGetProfile(GroupDto dto)
|
||||
{
|
||||
CheckConnection();
|
||||
if (!IsConnected) return new GroupProfileDto(Group: dto.Group, Description: null, Tags: null, PictureBase64: null, IsNsfw: false, IsDisabled: false);
|
||||
return await _lightlessHub!.InvokeAsync<GroupProfileDto>(nameof(GroupGetProfile), dto).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task GroupSetProfile(GroupProfileDto dto)
|
||||
{
|
||||
CheckConnection();
|
||||
await _lightlessHub!.InvokeAsync(nameof(GroupSetProfile), dto).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task<List<GroupFullInfoDto>> GroupsGetAll()
|
||||
{
|
||||
@@ -139,7 +151,6 @@ public partial class ApiController
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
|
||||
private void CheckConnection()
|
||||
{
|
||||
if (ServerState is not (ServerState.Connected or ServerState.Connecting or ServerState.Reconnecting)) throw new InvalidDataException("Not connected");
|
||||
|
||||
@@ -608,17 +608,7 @@ public sealed partial class ApiController : DisposableMediatorSubscriberBase, IL
|
||||
ServerState = state;
|
||||
}
|
||||
|
||||
public Task Client_GroupSendProfile(GroupProfileDto groupInfo)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<GroupProfileDto> GroupGetProfile(GroupDto dto)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task GroupSetProfile(GroupProfileDto dto)
|
||||
public Task<UserProfileDto?> UserGetLightfinderProfile(string hashedCid)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user