Files
MVP1/Assets/Scripts/Social/ChatPanel.cs
T

98 lines
3.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Text;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
// Панель чата: вкладки "Общий мир" / "Круг", лента сообщений, поле ввода и кнопка отправки.
public class ChatPanel : MonoBehaviour
{
[Header("Вкладки")]
public Button worldTabButton;
public Button circleTabButton;
[Header("Сообщения")]
public TMP_Text messagesText;
[Header("Ввод")]
public TMP_InputField inputField;
public Button sendButton;
const int MaxShownMessages = 30; // старые всё равно уходят за верхний край ленты
static readonly Color ActiveTabColor = new Color(0.16f, 0.35f, 0.7f);
static readonly Color InactiveTabColor = new Color(0.12f, 0.13f, 0.17f);
static readonly string[] NameColors = { "#6EC6FF", "#FF8A65", "#C792EA", "#81C784", "#FFD54F", "#4DD0E1" };
const string OwnNameColor = "#FFC857";
private ChatChannel currentChannel = ChatChannel.World;
private readonly StringBuilder sb = new StringBuilder();
void Start()
{
worldTabButton.onClick.AddListener(() => SwitchChannel(ChatChannel.World));
circleTabButton.onClick.AddListener(() => SwitchChannel(ChatChannel.Circle));
sendButton.onClick.AddListener(Send);
inputField.onSubmit.AddListener(_ => Send()); // Enter на клавиатуре
inputField.characterLimit = ChatService.MaxMessageLength;
ChatService.Instance.MessageReceived += OnMessageReceived;
SwitchChannel(ChatChannel.World);
}
void OnDestroy()
{
ChatService.Instance.MessageReceived -= OnMessageReceived;
}
void SwitchChannel(ChatChannel channel)
{
currentChannel = channel;
worldTabButton.image.color = channel == ChatChannel.World ? ActiveTabColor : InactiveTabColor;
circleTabButton.image.color = channel == ChatChannel.Circle ? ActiveTabColor : InactiveTabColor;
Redraw();
}
void Send()
{
if (ChatService.Instance.Send(currentChannel, inputField.text))
{
inputField.text = "";
}
inputField.ActivateInputField(); // курсор остаётся в поле -- можно писать дальше
}
void OnMessageReceived(ChatMessage message)
{
if (message.channel == currentChannel) Redraw();
}
void Redraw()
{
IReadOnlyList<ChatMessage> messages = ChatService.Instance.GetMessages(currentChannel);
int start = Mathf.Max(0, messages.Count - MaxShownMessages);
sb.Clear();
for (int i = start; i < messages.Count; i++)
{
ChatMessage m = messages[i];
string time = DateTimeOffset.FromUnixTimeMilliseconds(m.timeMs).ToLocalTime().ToString("HH:mm");
string color = m.senderId == MarchManager.LocalPlayerId ? OwnNameColor : GetNameColor(m.senderId);
if (sb.Length > 0) sb.Append('\n');
// <noparse> -- чтобы игрок не мог вставить в сообщение теги оформления
sb.Append($"<color=#9AA3B5>[{time}]</color> <color={color}>{m.senderName}:</color> <noparse>{m.text}</noparse>");
}
messagesText.text = sb.ToString();
}
// Один и тот же игрок -- всегда один цвет
static string GetNameColor(string senderId)
{
int hash = 0;
foreach (char c in senderId) hash = hash * 31 + c;
return NameColors[(hash & int.MaxValue) % NameColors.Length];
}
}