init 2
This commit is contained in:
701
LightlessSync/UI/EditProfileUi.Group.cs
Normal file
701
LightlessSync/UI/EditProfileUi.Group.cs
Normal file
@@ -0,0 +1,701 @@
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Colors;
|
||||
using Dalamud.Interface.Components;
|
||||
using Dalamud.Interface.ImGuiFileDialog;
|
||||
using Dalamud.Interface.Utility;
|
||||
using Dalamud.Interface.Utility.Raii;
|
||||
using LightlessSync.API.Data;
|
||||
using LightlessSync.API.Dto.Group;
|
||||
using LightlessSync.Services;
|
||||
using LightlessSync.Services.Mediator;
|
||||
using LightlessSync.UI.Tags;
|
||||
using LightlessSync.Utils;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.Formats;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace LightlessSync.UI;
|
||||
|
||||
public partial class EditProfileUi
|
||||
{
|
||||
private void OpenGroupEditor(GroupFullInfoDto groupInfo)
|
||||
{
|
||||
_mode = ProfileEditorMode.Group;
|
||||
_groupInfo = groupInfo;
|
||||
|
||||
var profile = _lightlessProfileManager.GetLightlessGroupProfile(groupInfo.Group);
|
||||
_groupProfileData = profile;
|
||||
SyncGroupProfileState(profile, resetSelection: true);
|
||||
|
||||
var scale = ImGuiHelpers.GlobalScale;
|
||||
var viewport = ImGui.GetMainViewport();
|
||||
ProfileEditorLayoutCoordinator.Enable(groupInfo.Group.GID);
|
||||
ProfileEditorLayoutCoordinator.EnsureAnchor(viewport.WorkPos, scale);
|
||||
Mediator.Publish(new GroupProfileOpenStandaloneMessage(groupInfo));
|
||||
|
||||
IsOpen = true;
|
||||
_wasOpen = true;
|
||||
}
|
||||
|
||||
private void ResetGroupEditorState()
|
||||
{
|
||||
_groupInfo = null;
|
||||
_groupProfileData = null;
|
||||
_groupIsNsfw = false;
|
||||
_groupIsDisabled = false;
|
||||
_groupServerIsNsfw = false;
|
||||
_groupServerIsDisabled = false;
|
||||
_queuedProfileImage = null;
|
||||
_queuedBannerImage = null;
|
||||
_profileImage = Array.Empty<byte>();
|
||||
_bannerImage = Array.Empty<byte>();
|
||||
_profileDescription = string.Empty;
|
||||
_descriptionText = string.Empty;
|
||||
_profileTagIds = Array.Empty<int>();
|
||||
_tagEditorSelection.Clear();
|
||||
_pfpTextureWrap?.Dispose();
|
||||
_pfpTextureWrap = null;
|
||||
_bannerTextureWrap?.Dispose();
|
||||
_bannerTextureWrap = null;
|
||||
_showProfileImageError = false;
|
||||
_showBannerImageError = false;
|
||||
}
|
||||
|
||||
private void DrawGroupEditor(float scale)
|
||||
{
|
||||
if (_groupInfo is null)
|
||||
{
|
||||
UiSharedService.TextWrapped("Open the Syncshell admin panel and choose a group to edit its profile.");
|
||||
return;
|
||||
}
|
||||
|
||||
var viewport = ImGui.GetMainViewport();
|
||||
var linked = ProfileEditorLayoutCoordinator.IsActive(_groupInfo.Group.GID);
|
||||
|
||||
if (linked)
|
||||
{
|
||||
ProfileEditorLayoutCoordinator.EnsureAnchor(viewport.WorkPos, scale);
|
||||
|
||||
var desiredSize = ProfileEditorLayoutCoordinator.GetEditorSize(scale);
|
||||
if (!ProfileEditorLayoutCoordinator.NearlyEquals(ImGui.GetWindowSize(), desiredSize))
|
||||
ImGui.SetWindowSize(desiredSize, ImGuiCond.Always);
|
||||
|
||||
var currentPos = ImGui.GetWindowPos();
|
||||
if (IsWindowBeingDragged())
|
||||
ProfileEditorLayoutCoordinator.UpdateAnchorFromEditor(currentPos, scale);
|
||||
|
||||
var desiredPos = ProfileEditorLayoutCoordinator.GetEditorPosition(scale);
|
||||
if (!ProfileEditorLayoutCoordinator.NearlyEquals(currentPos, desiredPos))
|
||||
ImGui.SetWindowPos(desiredPos, ImGuiCond.Always);
|
||||
}
|
||||
else
|
||||
{
|
||||
var defaultProfilePos = viewport.WorkPos + new Vector2(50f, 70f) * scale;
|
||||
var defaultEditorPos = defaultProfilePos + ProfileEditorLayoutCoordinator.GetEditorOffset(scale);
|
||||
ImGui.SetWindowPos(defaultEditorPos, ImGuiCond.FirstUseEver);
|
||||
}
|
||||
|
||||
if (_queuedProfileImage is not null)
|
||||
ApplyQueuedGroupProfileImage();
|
||||
if (_queuedBannerImage is not null)
|
||||
ApplyQueuedGroupBannerImage();
|
||||
|
||||
var profile = _lightlessProfileManager.GetLightlessGroupProfile(_groupInfo.Group);
|
||||
_groupProfileData = profile;
|
||||
SyncGroupProfileState(profile, resetSelection: false);
|
||||
|
||||
var accent = UIColors.Get("LightlessPurple");
|
||||
var accentBg = new Vector4(accent.X, accent.Y, accent.Z, 0.015f);
|
||||
var accentBorder = new Vector4(accent.X, accent.Y, accent.Z, 0.07f);
|
||||
|
||||
using var panelBg = ImRaii.PushColor(ImGuiCol.ChildBg, accentBg);
|
||||
using var panelBorder = ImRaii.PushColor(ImGuiCol.ChildBg, accentBorder);
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.ChildRounding, 4f * scale);
|
||||
|
||||
if (ImGui.BeginChild("##GroupProfileEditorCanvas", -Vector2.One, true, ImGuiWindowFlags.NoScrollbar))
|
||||
{
|
||||
DrawGroupGuidelinesSection(scale);
|
||||
ImGui.Dummy(new Vector2(0f, 4f * scale));
|
||||
DrawGroupProfileContent(profile, scale);
|
||||
}
|
||||
|
||||
ImGui.EndChild();
|
||||
ImGui.PopStyleVar();
|
||||
}
|
||||
|
||||
private void DrawGroupGuidelinesSection(float scale)
|
||||
{
|
||||
DrawSection("Guidelines", scale, () =>
|
||||
{
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, new Vector2(1f, 1f));
|
||||
|
||||
_uiSharedService.DrawNoteLine("# ", UIColors.Get("LightlessBlue"), "All users that are paired and unpaused with you will be able to see your profile pictures, tags and description.");
|
||||
_uiSharedService.DrawNoteLine("! ", UIColors.Get("LightlessYellow"), "Other users have the possibility to report this profile for breaking the rules.");
|
||||
_uiSharedService.DrawNoteLine("!!! ", UIColors.Get("DimRed"), "AVOID: Anything as profile image that can be considered highly illegal or obscene (bestiality, anything that could be considered a sexual act with a minor (that includes Lalafells), etc.)");
|
||||
_uiSharedService.DrawNoteLine("!!! ", UIColors.Get("DimRed"), "AVOID: Slurs of any kind in the description that can be considered highly offensive");
|
||||
_uiSharedService.DrawNoteLine("! ", UIColors.Get("LightlessYellow"), "In case of valid reports from other users this can lead to disabling the profile forever or terminating syncshell owner's Lightless account indefinitely.");
|
||||
_uiSharedService.DrawNoteLine("! ", UIColors.Get("LightlessYellow"), "Judgement of the profile validity from reports through staff is not up to debate and the decisions to disable the profile or your account permanent.");
|
||||
_uiSharedService.DrawNoteLine("! ", UIColors.Get("LightlessBlue"), "If the profile picture or profile description could be considered NSFW, enable the toggle in visibility settings.");
|
||||
|
||||
ImGui.PopStyleVar();
|
||||
});
|
||||
}
|
||||
|
||||
private void DrawGroupProfileContent(LightlessGroupProfileData profile, float scale)
|
||||
{
|
||||
DrawSection("Profile Preview", scale, () => DrawGroupProfileSnapshot(profile, scale));
|
||||
DrawSection("Profile Image", scale, DrawGroupProfileImageControls);
|
||||
DrawSection("Profile Banner", scale, DrawGroupProfileBannerControls);
|
||||
DrawSection("Profile Description", scale, DrawGroupProfileDescriptionEditor);
|
||||
DrawSection("Profile Tags", scale, () => DrawGroupProfileTagsEditor(scale));
|
||||
DrawSection("Visibility", scale, DrawGroupProfileVisibilityControls);
|
||||
}
|
||||
|
||||
private void DrawGroupProfileSnapshot(LightlessGroupProfileData profile, float scale)
|
||||
{
|
||||
var bannerHeight = 140f * scale;
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.ChildRounding, 4f * scale);
|
||||
if (ImGui.BeginChild("##GroupProfileBannerPreview", new Vector2(-1f, bannerHeight), true))
|
||||
{
|
||||
if (_bannerTextureWrap != null)
|
||||
{
|
||||
var childSize = ImGui.GetWindowSize();
|
||||
var padding = ImGui.GetStyle().WindowPadding;
|
||||
var contentSize = new Vector2(
|
||||
MathF.Max(childSize.X - padding.X * 2f, 1f),
|
||||
MathF.Max(childSize.Y - padding.Y * 2f, 1f));
|
||||
|
||||
var imageSize = ImGuiHelpers.ScaledVector2(_bannerTextureWrap.Width, _bannerTextureWrap.Height);
|
||||
if (imageSize.X > contentSize.X || imageSize.Y > contentSize.Y)
|
||||
{
|
||||
var ratio = MathF.Min(contentSize.X / MathF.Max(imageSize.X, 1f), contentSize.Y / MathF.Max(imageSize.Y, 1f));
|
||||
imageSize *= ratio;
|
||||
}
|
||||
|
||||
var offset = new Vector2(
|
||||
MathF.Max((contentSize.X - imageSize.X) * 0.5f, 0f),
|
||||
MathF.Max((contentSize.Y - imageSize.Y) * 0.5f, 0f));
|
||||
ImGui.SetCursorPos(padding + offset);
|
||||
ImGui.Image(_bannerTextureWrap.Handle, imageSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui.TextColored(UIColors.Get("LightlessPurple"), "No profile banner uploaded.");
|
||||
}
|
||||
}
|
||||
ImGui.EndChild();
|
||||
ImGui.PopStyleVar();
|
||||
|
||||
ImGui.Dummy(new Vector2(0f, 6f * scale));
|
||||
|
||||
if (_pfpTextureWrap != null)
|
||||
{
|
||||
var size = ImGuiHelpers.ScaledVector2(_pfpTextureWrap.Width, _pfpTextureWrap.Height);
|
||||
var maxEdge = 160f * scale;
|
||||
if (size.X > maxEdge || size.Y > maxEdge)
|
||||
{
|
||||
var ratio = MathF.Min(maxEdge / MathF.Max(size.X, 1f), maxEdge / MathF.Max(size.Y, 1f));
|
||||
size *= ratio;
|
||||
}
|
||||
|
||||
ImGui.Image(_pfpTextureWrap.Handle, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.ChildRounding, 4f * scale);
|
||||
if (ImGui.BeginChild("##GroupProfileImagePlaceholder", new Vector2(160f * scale, 160f * scale), true))
|
||||
ImGui.TextColored(UIColors.Get("LightlessPurple"), "No profile picture uploaded.");
|
||||
ImGui.EndChild();
|
||||
ImGui.PopStyleVar();
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGui.BeginGroup();
|
||||
ImGui.TextColored(UIColors.Get("LightlessBlue"), _groupInfo!.GroupAliasOrGID);
|
||||
ImGui.TextDisabled($"ID: {_groupInfo.Group.GID}");
|
||||
ImGui.TextDisabled($"Owner: {_groupInfo.Owner.AliasOrUID}");
|
||||
ImGui.EndGroup();
|
||||
|
||||
ImGui.Dummy(new Vector2(0f, 4f * scale));
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.ChildRounding, 4f * scale);
|
||||
if (ImGui.BeginChild("##GroupProfileDescriptionPreview", new Vector2(-1f, 120f * scale), true))
|
||||
{
|
||||
var hasDescription = !string.IsNullOrWhiteSpace(profile.Description);
|
||||
ImGui.PushTextWrapPos(ImGui.GetCursorPosX() + ImGui.GetContentRegionAvail().X);
|
||||
if (!hasDescription)
|
||||
{
|
||||
ImGui.TextDisabled("Syncshell has no description set.");
|
||||
}
|
||||
else if (!SeStringUtils.TryRenderSeStringMarkupAtCursor(profile.Description!))
|
||||
{
|
||||
UiSharedService.TextWrapped(profile.Description);
|
||||
}
|
||||
ImGui.PopTextWrapPos();
|
||||
}
|
||||
ImGui.EndChild();
|
||||
ImGui.PopStyleVar();
|
||||
|
||||
ImGui.Dummy(new Vector2(0f, 4f * scale));
|
||||
ImGui.TextColored(UIColors.Get("LightlessBlue"), "Saved Tags");
|
||||
var savedTags = _profileTagService.ResolveTags(_profileTagIds);
|
||||
if (savedTags.Count == 0)
|
||||
{
|
||||
ImGui.TextDisabled("-- No tags set --");
|
||||
}
|
||||
else
|
||||
{
|
||||
bool first = true;
|
||||
for (int i = 0; i < savedTags.Count; i++)
|
||||
{
|
||||
if (!savedTags[i].HasContent)
|
||||
continue;
|
||||
|
||||
if (!first)
|
||||
ImGui.SameLine(0f, 6f * scale);
|
||||
first = false;
|
||||
|
||||
using (ImRaii.PushId($"group-snapshot-tag-{i}"))
|
||||
DrawTagPreview(savedTags[i], scale, "##groupSnapshotTagPreview");
|
||||
}
|
||||
if (!first)
|
||||
ImGui.NewLine();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawGroupProfileImageControls()
|
||||
{
|
||||
_uiSharedService.DrawNoteLine("# ", UIColors.Get("LightlessBlue"), "Profile pictures must be 512x512 and under 2 MiB.");
|
||||
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.FileUpload, "Upload new profile picture"))
|
||||
{
|
||||
_fileDialogManager.OpenFileDialog("Select syncshell profile picture", ImageFileDialogFilter, (success, file) =>
|
||||
{
|
||||
if (!success || string.IsNullOrEmpty(file))
|
||||
return;
|
||||
_showProfileImageError = false;
|
||||
_ = SubmitGroupProfilePicture(file);
|
||||
});
|
||||
}
|
||||
UiSharedService.AttachToolTip("Select an image up to 512x512 pixels and <= 2 MiB (PNG/JPG/JPEG/WEBP/BMP).");
|
||||
ImGui.SameLine();
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Trash, "Clear profile picture"))
|
||||
{
|
||||
_ = ClearGroupProfilePicture();
|
||||
}
|
||||
UiSharedService.AttachToolTip("Remove the current profile picture from this syncshell.");
|
||||
|
||||
if (_showProfileImageError)
|
||||
{
|
||||
UiSharedService.ColorTextWrapped("Image must be no larger than 512x512 pixels and under 2 MiB.", ImGuiColors.DalamudRed);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawGroupProfileBannerControls()
|
||||
{
|
||||
_uiSharedService.DrawNoteLine("# ", UIColors.Get("LightlessBlue"), "Profile banners must be 840x260 and under 2 MiB.");
|
||||
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.FileUpload, "Upload new profile banner"))
|
||||
{
|
||||
_fileDialogManager.OpenFileDialog("Select syncshell profile banner", ImageFileDialogFilter, (success, file) =>
|
||||
{
|
||||
if (!success || string.IsNullOrEmpty(file))
|
||||
return;
|
||||
_showBannerImageError = false;
|
||||
_ = SubmitGroupProfileBanner(file);
|
||||
});
|
||||
}
|
||||
UiSharedService.AttachToolTip("Select an image up to 840x260 pixels and <= 2 MiB (PNG/JPG/JPEG/WEBP/BMP).");
|
||||
ImGui.SameLine();
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Trash, "Clear profile banner"))
|
||||
{
|
||||
_ = ClearGroupProfileBanner();
|
||||
}
|
||||
UiSharedService.AttachToolTip("Remove the current profile banner.");
|
||||
|
||||
if (_showBannerImageError)
|
||||
{
|
||||
UiSharedService.ColorTextWrapped("Banner must be no larger than 840x260 pixels and under 2 MiB.", ImGuiColors.DalamudRed);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawGroupProfileDescriptionEditor()
|
||||
{
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, new Vector2(6f, 4f) * ImGuiHelpers.GlobalScale);
|
||||
var descriptionBoxSize = new Vector2(-1f, 160f * ImGuiHelpers.GlobalScale);
|
||||
ImGui.InputTextMultiline("##GroupDescription", ref _descriptionText, 1500, descriptionBoxSize);
|
||||
ImGui.PopStyleVar();
|
||||
|
||||
ImGui.TextDisabled($"{_descriptionText.Length}/1500 characters");
|
||||
ImGui.SameLine();
|
||||
ImGuiComponents.HelpMarker(DescriptionMacroTooltip);
|
||||
|
||||
bool changed = !string.Equals(_descriptionText, _profileDescription, StringComparison.Ordinal);
|
||||
if (!changed)
|
||||
ImGui.BeginDisabled();
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Save, "Save Description"))
|
||||
{
|
||||
_ = SubmitGroupDescription(_descriptionText);
|
||||
}
|
||||
UiSharedService.AttachToolTip("Apply the text above to the syncshell profile description.");
|
||||
if (!changed)
|
||||
ImGui.EndDisabled();
|
||||
|
||||
ImGui.SameLine();
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Trash, "Clear Description"))
|
||||
{
|
||||
_ = SubmitGroupDescription(string.Empty);
|
||||
}
|
||||
UiSharedService.AttachToolTip("Remove the profile description.");
|
||||
}
|
||||
|
||||
private void DrawGroupProfileTagsEditor(float scale)
|
||||
{
|
||||
DrawTagEditor(
|
||||
scale,
|
||||
contextPrefix: "group",
|
||||
saveTooltip: "Apply the selected tags to this syncshell profile.",
|
||||
submitAction: payload => SubmitGroupTagChanges(payload),
|
||||
allowReorder: true,
|
||||
sortPayloadBeforeSubmit: true,
|
||||
onPayloadPrepared: payload =>
|
||||
{
|
||||
_tagEditorSelection.Clear();
|
||||
if (payload.Length > 0)
|
||||
_tagEditorSelection.AddRange(payload);
|
||||
});
|
||||
}
|
||||
|
||||
private void DrawGroupProfileVisibilityControls()
|
||||
{
|
||||
bool changedNsfw = DrawCheckboxRow("Profile is NSFW", _groupIsNsfw, out var newNsfw, "Flag this profile as not safe for work.");
|
||||
if (changedNsfw)
|
||||
_groupIsNsfw = newNsfw;
|
||||
|
||||
bool changedDisabled = DrawCheckboxRow("Disable profile for viewers", _groupIsDisabled, out var newDisabled, "Temporarily hide this profile from members.");
|
||||
if (changedDisabled)
|
||||
_groupIsDisabled = newDisabled;
|
||||
|
||||
bool visibilityChanged = (_groupIsNsfw != _groupServerIsNsfw) || (_groupIsDisabled != _groupServerIsDisabled);
|
||||
|
||||
if (!visibilityChanged)
|
||||
ImGui.BeginDisabled();
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Save, "Apply Visibility Changes"))
|
||||
{
|
||||
_ = SubmitGroupVisibilityChanges(_groupIsNsfw, _groupIsDisabled);
|
||||
}
|
||||
UiSharedService.AttachToolTip("Apply the visibility toggles above.");
|
||||
if (!visibilityChanged)
|
||||
ImGui.EndDisabled();
|
||||
|
||||
ImGui.SameLine();
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.SyncAlt, "Reset"))
|
||||
{
|
||||
_groupIsNsfw = _groupServerIsNsfw;
|
||||
_groupIsDisabled = _groupServerIsDisabled;
|
||||
}
|
||||
}
|
||||
|
||||
private string? GetCurrentGroupProfileImageBase64()
|
||||
{
|
||||
if (_queuedProfileImage is not null && _queuedProfileImage.Length > 0)
|
||||
return Convert.ToBase64String(_queuedProfileImage);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(_groupProfileData?.Base64ProfilePicture))
|
||||
return _groupProfileData!.Base64ProfilePicture;
|
||||
|
||||
return _profileImage.Length > 0 ? Convert.ToBase64String(_profileImage) : null;
|
||||
}
|
||||
|
||||
private string? GetCurrentGroupBannerBase64()
|
||||
{
|
||||
if (_queuedBannerImage is not null && _queuedBannerImage.Length > 0)
|
||||
return Convert.ToBase64String(_queuedBannerImage);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(_groupProfileData?.Base64BannerPicture))
|
||||
return _groupProfileData!.Base64BannerPicture;
|
||||
|
||||
return _bannerImage.Length > 0 ? Convert.ToBase64String(_bannerImage) : null;
|
||||
}
|
||||
|
||||
private async Task SubmitGroupProfilePicture(string filePath)
|
||||
{
|
||||
if (_groupInfo is null)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
var fileContent = await File.ReadAllBytesAsync(filePath).ConfigureAwait(false);
|
||||
await using var stream = new MemoryStream(fileContent);
|
||||
var format = await Image.DetectFormatAsync(stream).ConfigureAwait(false);
|
||||
if (!IsSupportedImageFormat(format))
|
||||
{
|
||||
_showProfileImageError = true;
|
||||
return;
|
||||
}
|
||||
|
||||
using var image = Image.Load<Rgba32>(fileContent);
|
||||
if (image.Width > 512 || image.Height > 512 || fileContent.Length > 2000 * 1024)
|
||||
{
|
||||
_showProfileImageError = true;
|
||||
return;
|
||||
}
|
||||
|
||||
await _apiController.GroupSetProfile(new GroupProfileDto(
|
||||
_groupInfo.Group,
|
||||
Description: null,
|
||||
Tags: null,
|
||||
PictureBase64: Convert.ToBase64String(fileContent),
|
||||
BannerBase64: null,
|
||||
IsNsfw: null,
|
||||
IsDisabled: null)).ConfigureAwait(false);
|
||||
|
||||
_showProfileImageError = false;
|
||||
_queuedProfileImage = fileContent;
|
||||
Mediator.Publish(new ClearProfileGroupDataMessage(_groupInfo.Group));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Failed to upload syncshell profile picture.");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ClearGroupProfilePicture()
|
||||
{
|
||||
if (_groupInfo is null)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
await _apiController.GroupSetProfile(new GroupProfileDto(
|
||||
_groupInfo.Group,
|
||||
Description: null,
|
||||
Tags: null,
|
||||
PictureBase64: null,
|
||||
BannerBase64: null,
|
||||
IsNsfw: null,
|
||||
IsDisabled: null)).ConfigureAwait(false);
|
||||
|
||||
_queuedProfileImage = Array.Empty<byte>();
|
||||
Mediator.Publish(new ClearProfileGroupDataMessage(_groupInfo.Group));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Failed to clear syncshell profile picture.");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SubmitGroupProfileBanner(string filePath)
|
||||
{
|
||||
if (_groupInfo is null)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
var fileContent = await File.ReadAllBytesAsync(filePath).ConfigureAwait(false);
|
||||
await using var stream = new MemoryStream(fileContent);
|
||||
var format = await Image.DetectFormatAsync(stream).ConfigureAwait(false);
|
||||
if (!IsSupportedImageFormat(format))
|
||||
{
|
||||
_showBannerImageError = true;
|
||||
return;
|
||||
}
|
||||
|
||||
using var image = Image.Load<Rgba32>(fileContent);
|
||||
if (image.Width > 840 || image.Height > 260 || fileContent.Length > 2000 * 1024)
|
||||
{
|
||||
_showBannerImageError = true;
|
||||
return;
|
||||
}
|
||||
|
||||
await _apiController.GroupSetProfile(new GroupProfileDto(
|
||||
_groupInfo.Group,
|
||||
Description: null,
|
||||
Tags: null,
|
||||
PictureBase64: null,
|
||||
BannerBase64: Convert.ToBase64String(fileContent),
|
||||
IsNsfw: null,
|
||||
IsDisabled: null)).ConfigureAwait(false);
|
||||
|
||||
_showBannerImageError = false;
|
||||
_queuedBannerImage = fileContent;
|
||||
Mediator.Publish(new ClearProfileGroupDataMessage(_groupInfo.Group));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Failed to upload syncshell profile banner.");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ClearGroupProfileBanner()
|
||||
{
|
||||
if (_groupInfo is null)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
await _apiController.GroupSetProfile(new GroupProfileDto(
|
||||
_groupInfo.Group,
|
||||
Description: null,
|
||||
Tags: null,
|
||||
PictureBase64: null,
|
||||
BannerBase64: null,
|
||||
IsNsfw: null,
|
||||
IsDisabled: null)).ConfigureAwait(false);
|
||||
|
||||
_queuedBannerImage = Array.Empty<byte>();
|
||||
Mediator.Publish(new ClearProfileGroupDataMessage(_groupInfo.Group));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Failed to clear syncshell profile banner.");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SubmitGroupDescription(string description)
|
||||
{
|
||||
if (_groupInfo is null)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
await _apiController.GroupSetProfile(new GroupProfileDto(
|
||||
_groupInfo.Group,
|
||||
Description: description,
|
||||
Tags: null,
|
||||
PictureBase64: GetCurrentGroupProfileImageBase64(),
|
||||
BannerBase64: GetCurrentGroupBannerBase64(),
|
||||
IsNsfw: null,
|
||||
IsDisabled: null)).ConfigureAwait(false);
|
||||
|
||||
_profileDescription = description;
|
||||
Mediator.Publish(new ClearProfileGroupDataMessage(_groupInfo.Group));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Failed to update syncshell profile description.");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SubmitGroupTagChanges(int[] payload)
|
||||
{
|
||||
if (_groupInfo is null)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
await _apiController.GroupSetProfile(new GroupProfileDto(
|
||||
_groupInfo.Group,
|
||||
Description: null,
|
||||
Tags: payload,
|
||||
PictureBase64: GetCurrentGroupProfileImageBase64(),
|
||||
BannerBase64: GetCurrentGroupBannerBase64(),
|
||||
IsNsfw: null,
|
||||
IsDisabled: null)).ConfigureAwait(false);
|
||||
|
||||
_profileTagIds = payload.Length == 0 ? Array.Empty<int>() : payload.ToArray();
|
||||
Mediator.Publish(new ClearProfileGroupDataMessage(_groupInfo.Group));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Failed to update syncshell profile tags.");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SubmitGroupVisibilityChanges(bool isNsfw, bool isDisabled)
|
||||
{
|
||||
if (_groupInfo is null)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
await _apiController.GroupSetProfile(new GroupProfileDto(
|
||||
_groupInfo.Group,
|
||||
Description: null,
|
||||
Tags: null,
|
||||
PictureBase64: GetCurrentGroupProfileImageBase64(),
|
||||
BannerBase64: GetCurrentGroupBannerBase64(),
|
||||
IsNsfw: isNsfw,
|
||||
IsDisabled: isDisabled)).ConfigureAwait(false);
|
||||
|
||||
_groupServerIsNsfw = isNsfw;
|
||||
_groupServerIsDisabled = isDisabled;
|
||||
Mediator.Publish(new ClearProfileGroupDataMessage(_groupInfo.Group));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Failed to update syncshell profile visibility.");
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyQueuedGroupProfileImage()
|
||||
{
|
||||
if (_queuedProfileImage is null)
|
||||
return;
|
||||
|
||||
_profileImage = _queuedProfileImage;
|
||||
_pfpTextureWrap?.Dispose();
|
||||
_pfpTextureWrap = _profileImage.Length > 0 ? _uiSharedService.LoadImage(_profileImage) : null;
|
||||
_queuedProfileImage = null;
|
||||
}
|
||||
|
||||
private void ApplyQueuedGroupBannerImage()
|
||||
{
|
||||
if (_queuedBannerImage is null)
|
||||
return;
|
||||
|
||||
_bannerImage = _queuedBannerImage;
|
||||
_bannerTextureWrap?.Dispose();
|
||||
_bannerTextureWrap = _bannerImage.Length > 0 ? _uiSharedService.LoadImage(_bannerImage) : null;
|
||||
_queuedBannerImage = null;
|
||||
}
|
||||
|
||||
private void SyncGroupProfileState(LightlessGroupProfileData profile, bool resetSelection)
|
||||
{
|
||||
if (!_profileImage.SequenceEqual(profile.ProfileImageData.Value))
|
||||
{
|
||||
_profileImage = profile.ProfileImageData.Value;
|
||||
_pfpTextureWrap?.Dispose();
|
||||
_pfpTextureWrap = _profileImage.Length > 0 ? _uiSharedService.LoadImage(_profileImage) : null;
|
||||
}
|
||||
|
||||
if (!_bannerImage.SequenceEqual(profile.BannerImageData.Value))
|
||||
{
|
||||
_bannerImage = profile.BannerImageData.Value;
|
||||
_bannerTextureWrap?.Dispose();
|
||||
_bannerTextureWrap = _bannerImage.Length > 0 ? _uiSharedService.LoadImage(_bannerImage) : null;
|
||||
}
|
||||
|
||||
if (!string.Equals(_profileDescription, profile.Description, StringComparison.Ordinal))
|
||||
{
|
||||
_profileDescription = profile.Description;
|
||||
_descriptionText = _profileDescription;
|
||||
}
|
||||
|
||||
var tags = profile.Tags ?? Array.Empty<int>();
|
||||
if (!TagsEqual(tags, _profileTagIds))
|
||||
{
|
||||
_profileTagIds = tags.Count == 0 ? Array.Empty<int>() : tags.ToArray();
|
||||
if (resetSelection)
|
||||
{
|
||||
_tagEditorSelection.Clear();
|
||||
if (_profileTagIds.Length > 0)
|
||||
_tagEditorSelection.AddRange(_profileTagIds);
|
||||
}
|
||||
}
|
||||
|
||||
_groupIsNsfw = profile.IsNsfw;
|
||||
_groupIsDisabled = profile.IsDisabled;
|
||||
_groupServerIsNsfw = profile.IsNsfw;
|
||||
_groupServerIsDisabled = profile.IsDisabled;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user