252 lines
8.1 KiB
C#
252 lines
8.1 KiB
C#
using System.Numerics;
|
|
using Content.Client._Sunrise.Messenger;
|
|
using Content.Client.Resources;
|
|
using Content.Client.Stylesheets;
|
|
using Content.Shared._Sunrise.Messenger;
|
|
using Content.Shared.StatusIcon;
|
|
using Robust.Client.AutoGenerated;
|
|
using Robust.Client.GameObjects;
|
|
using Robust.Client.Graphics;
|
|
using Robust.Client.ResourceManagement;
|
|
using Robust.Client.UserInterface.Controls;
|
|
using Robust.Client.UserInterface.CustomControls;
|
|
using Robust.Client.UserInterface.RichText;
|
|
using Robust.Client.UserInterface.XAML;
|
|
using Robust.Shared.Prototypes;
|
|
using Robust.Shared.Utility;
|
|
|
|
namespace Content.Client._Sunrise.CartridgeLoader.Cartridges;
|
|
|
|
[GenerateTypedNameReferences]
|
|
public sealed partial class MessagePanel : PanelContainer
|
|
{
|
|
[Dependency] private readonly IResourceCache _resourceCache = default!;
|
|
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
|
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
|
[Dependency] private readonly NetTexturesManager _netTexturesManager = default!;
|
|
|
|
private ClientEmojiSystem? EmojiSystem => _entitySystemManager.GetEntitySystemOrNull<ClientEmojiSystem>();
|
|
private SpriteSystem GetSpriteSystem() => _entitySystemManager.GetEntitySystem<SpriteSystem>();
|
|
|
|
/// <summary>
|
|
/// ID сообщения для идентификации при обновлении
|
|
/// </summary>
|
|
public long MessageId { get; private set; }
|
|
|
|
private static readonly Type[] MessageTagsAllowed =
|
|
[
|
|
typeof(BoldItalicTag),
|
|
typeof(BoldTag),
|
|
typeof(BulletTag),
|
|
typeof(ColorTag),
|
|
typeof(HeadingTag),
|
|
typeof(ItalicTag),
|
|
typeof(EmojiTag),
|
|
];
|
|
|
|
public MessagePanel()
|
|
{
|
|
IoCManager.InjectDependencies(this);
|
|
RobustXamlLoader.Load(this);
|
|
_netTexturesManager.ResourceLoaded += OnResourceLoaded;
|
|
ImageButton.OnPressed += _ => ShowFullImage();
|
|
|
|
ImageBorder.PanelOverride = new StyleBoxFlat
|
|
{
|
|
BackgroundColor = Color.Transparent,
|
|
BorderColor = Color.Transparent,
|
|
BorderThickness = new Thickness(2)
|
|
};
|
|
|
|
ImageButton.OnMouseEntered += _ =>
|
|
{
|
|
if (ImageBorder.PanelOverride is StyleBoxFlat style)
|
|
{
|
|
style.BorderColor = Color.White.WithAlpha(0.6f);
|
|
}
|
|
};
|
|
|
|
ImageButton.OnMouseExited += _ =>
|
|
{
|
|
if (ImageBorder.PanelOverride is StyleBoxFlat style)
|
|
{
|
|
style.BorderColor = Color.Transparent;
|
|
}
|
|
};
|
|
}
|
|
|
|
public event Action<long>? OnDeleteMessage;
|
|
private Button? _deleteButton;
|
|
private string? _currentImagePath;
|
|
|
|
public void UpdateMessage(MessengerMessage message, bool isOwnMessage, bool isPersonalChat, string? currentUserId)
|
|
{
|
|
MessageId = message.MessageId;
|
|
SenderLabel.Text = message.SenderName;
|
|
TimeLabel.Text = message.Timestamp.ToString(@"hh\:mm");
|
|
|
|
UpdateJobIcon(message.SenderJobIconId);
|
|
|
|
var parsedContent = EmojiSystem?.ParseEmojis(message.Content) ?? message.Content;
|
|
ContentLabel.SetMessage(FormattedMessage.FromMarkupPermissive(parsedContent), MessageTagsAllowed);
|
|
ContentLabel.Visible = !string.IsNullOrWhiteSpace(message.Content);
|
|
|
|
if (isOwnMessage && _deleteButton == null)
|
|
{
|
|
_deleteButton = new Button
|
|
{
|
|
Text = "✖",
|
|
SetWidth = 24,
|
|
SetHeight = 24,
|
|
ToolTip = Loc.GetString("messenger-delete-message"),
|
|
Margin = new Thickness(2, 0)
|
|
};
|
|
_deleteButton.AddStyleClass(StyleClass.ButtonSmall);
|
|
_deleteButton.OnPressed += _ => OnDeleteMessage?.Invoke(MessageId);
|
|
RightContainer.AddChild(_deleteButton);
|
|
}
|
|
else if (!isOwnMessage && _deleteButton != null)
|
|
{
|
|
RightContainer.RemoveChild(_deleteButton);
|
|
_deleteButton = null;
|
|
}
|
|
|
|
var roundedButtonTex = _resourceCache.GetTexture("/Textures/Interface/Nano/rounded_button_bordered.svg.96dpi.png");
|
|
var roundedStyleBox = new StyleBoxTexture
|
|
{
|
|
Texture = roundedButtonTex
|
|
};
|
|
roundedStyleBox.SetPatchMargin(StyleBox.Margin.All, 5);
|
|
roundedStyleBox.SetPadding(StyleBox.Margin.All, 2);
|
|
roundedStyleBox.SetContentMarginOverride(StyleBox.Margin.Left, 8);
|
|
roundedStyleBox.SetContentMarginOverride(StyleBox.Margin.Right, 8);
|
|
roundedStyleBox.SetContentMarginOverride(StyleBox.Margin.Top, 6);
|
|
roundedStyleBox.SetContentMarginOverride(StyleBox.Margin.Bottom, 6);
|
|
|
|
if (isOwnMessage)
|
|
{
|
|
roundedStyleBox.Modulate = Color.FromHex("#2A4A5A");
|
|
}
|
|
else
|
|
{
|
|
roundedStyleBox.Modulate = Color.FromHex("#1E1E22");
|
|
}
|
|
|
|
MessagePanelContainer.PanelOverride = roundedStyleBox;
|
|
|
|
if (isPersonalChat && isOwnMessage && message.RecipientId != null)
|
|
{
|
|
ReadStatusIcon.Visible = true;
|
|
var readStatusTexturePath = message.IsRead
|
|
? new ResPath("/Textures/Interface/Actions/eyeopen.png")
|
|
: new ResPath("/Textures/Interface/Actions/eyeclose.png");
|
|
ReadStatusIcon.Texture = _resourceCache.GetTexture(readStatusTexturePath);
|
|
}
|
|
else
|
|
{
|
|
ReadStatusIcon.Visible = false;
|
|
}
|
|
|
|
UpdateImagePreview(message.ImagePath);
|
|
}
|
|
|
|
private void UpdateImagePreview(string? imagePath)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(imagePath))
|
|
{
|
|
ImageButton.Visible = false;
|
|
_currentImagePath = null;
|
|
return;
|
|
}
|
|
|
|
_currentImagePath = imagePath;
|
|
|
|
var isAvailable = _netTexturesManager.EnsureResource(imagePath);
|
|
|
|
if (isAvailable)
|
|
{
|
|
LoadImageTexture(imagePath);
|
|
}
|
|
else
|
|
{
|
|
ImageButton.Visible = false;
|
|
}
|
|
}
|
|
|
|
private void ShowFullImage()
|
|
{
|
|
if (ImagePreview.Texture == null)
|
|
return;
|
|
|
|
var window = new DefaultWindow
|
|
{
|
|
Title = Loc.GetString("messenger-image-preview-title"),
|
|
MinSize = new Vector2(600, 600)
|
|
};
|
|
|
|
var textureRect = new TextureRect
|
|
{
|
|
Texture = ImagePreview.Texture,
|
|
Stretch = TextureRect.StretchMode.KeepAspect,
|
|
HorizontalExpand = true,
|
|
VerticalExpand = true
|
|
};
|
|
|
|
window.Contents.AddChild(textureRect);
|
|
window.OpenCentered();
|
|
}
|
|
|
|
private void OnResourceLoaded(string resourcePath)
|
|
{
|
|
if (_currentImagePath == resourcePath)
|
|
{
|
|
LoadImageTexture(resourcePath);
|
|
}
|
|
}
|
|
|
|
private void LoadImageTexture(string imagePath)
|
|
{
|
|
try
|
|
{
|
|
var uploadedPath = _netTexturesManager.GetUploadedPath(imagePath);
|
|
if (_resourceCache.TryGetResource<TextureResource>(uploadedPath, out var textureResource))
|
|
{
|
|
ImagePreview.Texture = textureResource.Texture;
|
|
ImageButton.Visible = true;
|
|
}
|
|
else
|
|
{
|
|
ImageButton.Visible = false;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
ImageButton.Visible = false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Обновляет иконку работы в панели сообщения
|
|
/// </summary>
|
|
private void UpdateJobIcon(ProtoId<JobIconPrototype>? jobIconId)
|
|
{
|
|
if (jobIconId != null && _prototypeManager.TryIndex(jobIconId.Value, out JobIconPrototype? jobIcon))
|
|
{
|
|
JobIconRect.Texture = GetSpriteSystem().Frame0(jobIcon.Icon);
|
|
JobIconRect.Visible = true;
|
|
}
|
|
else
|
|
{
|
|
var unknownIconId = new ProtoId<JobIconPrototype>("JobIconUnknown");
|
|
if (_prototypeManager.TryIndex(unknownIconId, out JobIconPrototype? unknownIcon))
|
|
{
|
|
JobIconRect.Texture = GetSpriteSystem().Frame0(unknownIcon.Icon);
|
|
JobIconRect.Visible = true;
|
|
}
|
|
else
|
|
{
|
|
JobIconRect.Visible = false;
|
|
}
|
|
}
|
|
}
|
|
}
|