Files
source/Assets/Scripts/ChatroomMenu.cs
2026-02-01 23:00:13 -07:00

422 lines
22 KiB
C#

using System.Collections;
using System.Numerics;
using System.Threading.Tasks;
using MikeSchweitzer.WebSocket;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class ChatroomMenu : MonoBehaviour
{
[SerializeField] private TMP_Text statusText;
[SerializeField] private Button backButton;
[SerializeField] private Button sendButton;
[SerializeField] private TMP_InputField messageInputField;
[SerializeField] private GameObject content;
[SerializeField] private GameObject sampleObject;
[SerializeField] private Button downButton;
[SerializeField] private ProfileMenu profilePrefab;
[SerializeField] private GameObject optionsPanel;
[SerializeField] private Button optionsPanelExitButton;
[SerializeField] private Button optionsPanelDeleteButton;
[SerializeField] private Button optionsPanelEditButton;
[SerializeField] private Button optionsPanelReportButton;
[SerializeField] private Button optionsPanelCopyButton;
private ChatroomMessage selectedMessageForOptions;
[SerializeField] private GameObject editMessagePanelSample;
private GameObject editMessagePanelCurrent;
[SerializeField] private GameObject reportMessagePanel;
[SerializeField] private Button reportMessagePanelExitButton;
[SerializeField] private Button reportMessagePanelSubmitButton;
[SerializeField] private TMP_InputField reportMessagePanelReportReason;
void Awake()
{
messageInputField.onSelect.AddListener((_) => messageInputField.caretPosition = messageInputField.text.Length);
reportMessagePanelReportReason.onSelect.AddListener((_) => reportMessagePanelReportReason.caretPosition = reportMessagePanelReportReason.text.Length);
WebsocketHandler.Instance._Connection.StateChanged += OnStateChanged;
WebsocketHandler.Instance._Connection.MessageReceived += OnMessageReceived;
if (WebsocketHandler.Instance._Connection.State == WebSocketState.Connected)
{
statusText.text = "Loading messages";
RequestInfoMessage msg = new()
{
kind = "chatroom_messages"
};
WebsocketHandler.Instance._Connection.AddOutgoingMessage(JsonUtility.ToJson(msg));
}
}
private void OnStateChanged(WebSocketConnection connection, WebSocketState oldState, WebSocketState newState)
{
if (newState == WebSocketState.Connected)
{
statusText.text = "Loading messages";
RequestInfoMessage msg = new()
{
kind = "chatroom_messages"
};
WebsocketHandler.Instance._Connection.AddOutgoingMessage(JsonUtility.ToJson(msg));
}
}
private void OnMessageReceived(WebSocketConnection connection, WebSocketMessage message)
{
if (message.String != null && connection.State == WebSocketState.Connected)
{
JToken data = JToken.Parse(message.String);
if (data["for"] != null)
{
if (data["for"].ToString() == "info_request:chatroom_messages")
{
var userId = BazookaManager.Instance.GetAccountID();
foreach (Transform item in content.transform)
{
if (!item.gameObject.activeSelf) continue;
Destroy(item.gameObject);
break;
}
foreach (var chatMessage in data["data"].ToObject<ChatroomMessage[]>())
{
InsertMessage(chatMessage, userId);
}
statusText.text = "";
StartCoroutine(ScrollToBottom());
CustomIconLoader.Init(FindObjectsByType<WaitingForCustomIcon>(FindObjectsSortMode.None));
}
else if (data["for"].ToString() == "upload:chatroom_message")
{
var userId = BazookaManager.Instance.GetAccountID();
var chatMessage = data["data"].ToObject<ChatroomMessage>();
Destroy(content.transform.GetChild(1).gameObject);
InsertMessage(chatMessage, userId);
CustomIconLoader.Init(FindObjectsByType<WaitingForCustomIcon>(FindObjectsSortMode.None));
}
else if (data["for"].ToString() == "delete:chatroom_message")
{
Destroy(content.transform.Find("ChatroomRow_" + data["data"]["id"].ToString() ?? "").gameObject);
if (data["data"]["fillerMessage"].ToString() != null)
{
var userId = BazookaManager.Instance.GetAccountID();
var chatMessage = data["data"]["fillerMessage"].ToObject<ChatroomMessage>();
var row = InsertMessage(chatMessage, userId);
row.transform.SetSiblingIndex(1);
CustomIconLoader.Init(FindObjectsByType<WaitingForCustomIcon>(FindObjectsSortMode.None));
}
}
else if (data["for"].ToString() == "edit:chatroom_message")
{
if (data["data"]["newContent"].ToString() != null)
{
content.transform.Find("ChatroomRow_" + data["data"]["id"].ToString()).transform.GetChild(3).GetComponent<TMP_Text>().text = data["data"]["newContent"].ToString();
}
}
}
}
}
GameObject InsertMessage(ChatroomMessage message, BigInteger? localUserId)
{
var obj = content.transform.Find("ChatroomRow_" + message.ID);
var rowInfo = Instantiate(sampleObject, content.transform);
rowInfo.transform.SetSiblingIndex(content.transform.childCount - 1);
var bgImg = rowInfo.transform.GetChild(0).GetComponent<Image>();
var usernameText = rowInfo.transform.GetChild(1).GetComponent<TMP_Text>();
var playerIcon = rowInfo.transform.GetChild(2).GetComponent<Image>();
var playerIconButton = rowInfo.transform.GetChild(2).GetComponent<Button>();
var playerOverlayIcon = playerIcon.transform.GetChild(0).GetComponent<Image>();
var messageText = rowInfo.transform.GetChild(3).GetComponent<TMP_Text>();
var optionsButton = rowInfo.transform.GetChild(4).GetComponent<Button>();
usernameText.text = message.Username;
messageText.text = message.Content;
if (message.CustomIcon == null)
{
playerIcon.sprite = Resources.Load<Sprite>("Icons/Icons/bird_" + message.Icon);
if (message.Icon == 1) playerIcon.sprite = Tools.GetIconForUser(message.UserID);
playerOverlayIcon.sprite = Resources.Load<Sprite>("Icons/Overlays/overlay_" + message.Overlay);
if (message.Overlay != 0) playerOverlayIcon.gameObject.SetActive(true);
if (message.Overlay == 8) playerOverlayIcon.transform.localPosition = new UnityEngine.Vector2(-16.56f, 14.81f);
else if (message.Overlay == 11) playerOverlayIcon.transform.localPosition = new UnityEngine.Vector2(-14.74451f, 20.39122f);
else if (message.Overlay == 13) playerOverlayIcon.transform.localPosition = new UnityEngine.Vector2(-16.54019f, 14.70365f);
try
{
playerIcon.color = new Color(message.BirdColor[0] / 255f, message.BirdColor[1] / 255f, message.BirdColor[2] / 255f);
playerOverlayIcon.color = new Color(message.OverlayColor[0] / 255f, message.OverlayColor[1] / 255f, message.OverlayColor[2] / 255f);
}
catch
{
playerIcon.color = Color.white;
playerOverlayIcon.color = Color.white;
}
}
else playerIcon.gameObject.AddComponent<WaitingForCustomIcon>().ID = message.CustomIcon;
playerIconButton.onClick.AddListener(async () =>
{
var clone = Instantiate(profilePrefab.gameObject, profilePrefab.gameObject.transform.parent);
clone.SetActive(true);
await clone.GetComponent<ProfileMenu>().Init(message.UserID);
});
optionsButton.onClick.AddListener(() => OptionsButtonClick(message, localUserId ?? 0));
rowInfo.name = "ChatroomRow_" + message.ID;
var entryComponet = rowInfo.AddComponent<ChatroomMenuEntry>();
entryComponet.Init(bgImg, optionsButton);
rowInfo.SetActive(true);
return rowInfo;
}
void OnDestroy()
{
WebsocketHandler.Instance._Connection.StateChanged -= OnStateChanged;
WebsocketHandler.Instance._Connection.MessageReceived -= OnMessageReceived;
}
void Start()
{
reportMessagePanelReportReason.transform.GetChild(0).GetChild(1).GetComponent<TMP_Text>().textWrappingMode = TextWrappingModes.Normal;
if (BazookaManager.Instance.GetAccountID() == null || BazookaManager.Instance.GetAccountName() == null || BazookaManager.Instance.GetAccountSession() == null)
{
sendButton.interactable = false;
messageInputField.interactable = false;
}
sendButton.onClick.AddListener(HandleMessageSubmit);
downButton.onClick.AddListener(() => StartCoroutine(ScrollToBottom()));
messageInputField.textComponent.textWrappingMode = TextWrappingModes.Normal;
messageInputField.onSubmit.AddListener(_ => HandleMessageSubmit());
optionsPanelExitButton.onClick.AddListener(() =>
{
optionsPanel.SetActive(false);
selectedMessageForOptions = null;
});
optionsPanelDeleteButton.onClick.AddListener(() => { if (selectedMessageForOptions != null) HandleMessageDelete(); });
optionsPanelDeleteButton.onClick.AddListener(optionsPanelExitButton.onClick.Invoke);
optionsPanelEditButton.onClick.AddListener(() =>
{
var editMessage = Instantiate(editMessagePanelSample, editMessagePanelSample.transform.parent);
editMessagePanelCurrent = editMessage;
var editMessageChild = editMessage.transform.GetChild(0);
var editMessageChildExitButton = editMessageChild.GetChild(0).GetComponent<Button>();
var editMessageChildSubmitButton = editMessageChild.GetChild(1).GetComponent<Button>();
var editMessageChildOriginalPreview = editMessageChild.GetChild(2).gameObject;
var editMessageChildEditedPreview = editMessageChild.GetChild(3).gameObject;
var editMessageChildNewContentInputBox = editMessageChild.GetChild(4).GetComponent<TMP_InputField>();
editMessageChildNewContentInputBox.onSelect.AddListener((_) => editMessageChildNewContentInputBox.caretPosition = editMessageChildNewContentInputBox.text.Length);
editMessageChildNewContentInputBox.text = selectedMessageForOptions.Content;
editMessageChildExitButton.onClick.AddListener(() =>
{
editMessagePanelCurrent = null;
Destroy(editMessage);
optionsPanel.SetActive(true);
});
editMessageChildSubmitButton.onClick.AddListener(() =>
{
HandleMessageEdit();
editMessagePanelCurrent = null;
Destroy(editMessage);
selectedMessageForOptions = null;
});
var rowInfo = editMessageChild.GetChild(2);
var usernameText = rowInfo.transform.GetChild(2).GetComponent<TMP_Text>();
var playerIcon = rowInfo.transform.GetChild(3).GetComponent<Image>();
var playerOverlayIcon = playerIcon.transform.GetChild(0).GetComponent<Image>();
var messageText = rowInfo.transform.GetChild(4).GetComponent<TMP_Text>();
var optionsButton = rowInfo.transform.GetChild(5).GetComponent<Button>();
usernameText.text = selectedMessageForOptions.Username;
messageText.text = selectedMessageForOptions.Content;
if (selectedMessageForOptions.CustomIcon == null)
{
playerIcon.sprite = Resources.Load<Sprite>("Icons/Icons/bird_" + selectedMessageForOptions.Icon);
if (selectedMessageForOptions.Icon == 1) playerIcon.sprite = Tools.GetIconForUser(selectedMessageForOptions.UserID);
playerOverlayIcon.sprite = Resources.Load<Sprite>("Icons/Overlays/overlay_" + selectedMessageForOptions.Overlay);
if (selectedMessageForOptions.Overlay != 0) playerOverlayIcon.gameObject.SetActive(true);
if (selectedMessageForOptions.Overlay == 8) playerOverlayIcon.transform.localPosition = new UnityEngine.Vector2(-16.56f, 14.81f);
else if (selectedMessageForOptions.Overlay == 11) playerOverlayIcon.transform.localPosition = new UnityEngine.Vector2(-14.74451f, 20.39122f);
else if (selectedMessageForOptions.Overlay == 13) playerOverlayIcon.transform.localPosition = new UnityEngine.Vector2(-16.54019f, 14.70365f);
try
{
playerIcon.color = new Color(selectedMessageForOptions.BirdColor[0] / 255f, selectedMessageForOptions.BirdColor[1] / 255f, selectedMessageForOptions.BirdColor[2] / 255f);
playerOverlayIcon.color = new Color(selectedMessageForOptions.OverlayColor[0] / 255f, selectedMessageForOptions.OverlayColor[1] / 255f, selectedMessageForOptions.OverlayColor[2] / 255f);
}
catch
{
playerIcon.color = Color.white;
playerOverlayIcon.color = Color.white;
}
}
else playerIcon.gameObject.AddComponent<WaitingForCustomIcon>().ID = selectedMessageForOptions.CustomIcon;
rowInfo = editMessageChild.GetChild(3);
usernameText = rowInfo.transform.GetChild(2).GetComponent<TMP_Text>();
playerIcon = rowInfo.transform.GetChild(3).GetComponent<Image>();
playerOverlayIcon = playerIcon.transform.GetChild(0).GetComponent<Image>();
messageText = rowInfo.transform.GetChild(4).GetComponent<TMP_Text>();
optionsButton = rowInfo.transform.GetChild(5).GetComponent<Button>();
usernameText.text = selectedMessageForOptions.Username;
messageText.text = selectedMessageForOptions.Content;
editMessageChildNewContentInputBox.onValueChanged.AddListener((value) => messageText.text = value);
if (selectedMessageForOptions.CustomIcon == null)
{
playerIcon.sprite = Resources.Load<Sprite>("Icons/Icons/bird_" + selectedMessageForOptions.Icon);
if (selectedMessageForOptions.Icon == 1) playerIcon.sprite = Tools.GetIconForUser(selectedMessageForOptions.UserID);
playerOverlayIcon.sprite = Resources.Load<Sprite>("Icons/Overlays/overlay_" + selectedMessageForOptions.Overlay);
if (selectedMessageForOptions.Overlay != 0) playerOverlayIcon.gameObject.SetActive(true);
if (selectedMessageForOptions.Overlay == 8) playerOverlayIcon.transform.localPosition = new UnityEngine.Vector2(-16.56f, 14.81f);
else if (selectedMessageForOptions.Overlay == 11) playerOverlayIcon.transform.localPosition = new UnityEngine.Vector2(-14.74451f, 20.39122f);
else if (selectedMessageForOptions.Overlay == 13) playerOverlayIcon.transform.localPosition = new UnityEngine.Vector2(-16.54019f, 14.70365f);
try
{
playerIcon.color = new Color(selectedMessageForOptions.BirdColor[0] / 255f, selectedMessageForOptions.BirdColor[1] / 255f, selectedMessageForOptions.BirdColor[2] / 255f);
playerOverlayIcon.color = new Color(selectedMessageForOptions.OverlayColor[0] / 255f, selectedMessageForOptions.OverlayColor[1] / 255f, selectedMessageForOptions.OverlayColor[2] / 255f);
}
catch
{
playerIcon.color = Color.white;
playerOverlayIcon.color = Color.white;
}
}
else playerIcon.gameObject.AddComponent<WaitingForCustomIcon>().ID = selectedMessageForOptions.CustomIcon;
optionsPanel.SetActive(false);
editMessage.SetActive(true);
CustomIconLoader.Init(FindObjectsByType<WaitingForCustomIcon>(FindObjectsSortMode.None));
});
optionsPanelReportButton.onClick.AddListener(() =>
{
reportMessagePanelReportReason.text = "";
optionsPanel.SetActive(false);
reportMessagePanel.SetActive(true);
});
reportMessagePanelExitButton.onClick.AddListener(() =>
{
editMessagePanelCurrent = null;
reportMessagePanel.SetActive(false);
optionsPanel.SetActive(true);
});
reportMessagePanelSubmitButton.onClick.AddListener(async () =>
{
reportMessagePanel.SetActive(false);
await HandleMessageReport();
editMessagePanelCurrent = null;
selectedMessageForOptions = null;
});
optionsPanelCopyButton.onClick.AddListener(() =>
{
if (selectedMessageForOptions != null) GUIUtility.systemCopyBuffer = selectedMessageForOptions.Content;
});
optionsPanelCopyButton.onClick.AddListener(optionsPanelExitButton.onClick.Invoke);
}
void HandleMessageSubmit()
{
if (messageInputField.text.Trim() == string.Empty) return;
sendButton.interactable = false;
backButton.interactable = false;
messageInputField.interactable = false;
UploadMessage msg = new()
{
kind = "chatroom_message",
data = new JObject()
{
["content"] = messageInputField.text,
["auth"] = BazookaManager.Instance.GetAccountSession()
}
};
WebsocketHandler.Instance._Connection.AddOutgoingMessage(JsonConvert.SerializeObject(msg));
sendButton.interactable = true;
backButton.interactable = true;
messageInputField.text = string.Empty;
messageInputField.interactable = true;
StartCoroutine(ScrollToBottom());
}
void HandleMessageDelete()
{
DeleteMessage msg = new()
{
kind = "chatroom_message",
data = new JObject()
{
["id"] = (int)selectedMessageForOptions.ID,
["auth"] = BazookaManager.Instance.GetAccountSession()
}
};
WebsocketHandler.Instance._Connection.AddOutgoingMessage(JsonConvert.SerializeObject(msg));
StartCoroutine(ScrollToBottom());
}
void HandleMessageEdit()
{
var newContent = editMessagePanelCurrent.transform.GetChild(0).GetChild(4).GetComponent<TMP_InputField>().text;
selectedMessageForOptions.Content = newContent;
EditMessage msg = new()
{
kind = "chatroom_message",
data = new JObject()
{
["id"] = (int)selectedMessageForOptions.ID,
["newContent"] = newContent,
["auth"] = BazookaManager.Instance.GetAccountSession()
}
};
WebsocketHandler.Instance._Connection.AddOutgoingMessage(JsonConvert.SerializeObject(msg));
StartCoroutine(ScrollToBottom());
}
async Task HandleMessageReport()
{
WWWForm dataForm = new();
dataForm.AddField("id", selectedMessageForOptions.ID.ToString());
dataForm.AddField("reason", reportMessagePanelReportReason.text);
using UnityWebRequest request = UnityWebRequest.Post(Endpoints.CHATROOM_REPORT_MESSAGE_ENDPOINT, dataForm);
request.SetRequestHeader("Authorization", BazookaManager.Instance.GetAccountSession());
request.SetRequestHeader("Requester", "BerryDashClient");
request.SetRequestHeader("ClientVersion", Application.version);
request.SetRequestHeader("ClientPlatform", Application.platform.ToString());
await request.SendWebRequest();
StartCoroutine(ScrollToBottom());
}
async void Update()
{
var max = content.GetComponent<RectTransform>().sizeDelta.y;
var current = content.transform.localPosition.y;
downButton.gameObject.SetActive(Mathf.Abs(max - current) > 0.1f * max);
if (Keyboard.current.escapeKey.wasPressedThisFrame && FindFirstObjectByType<ProfileMenu>() == null)
{
if (optionsPanel.activeSelf) optionsPanelExitButton.onClick.Invoke();
else if (reportMessagePanel.activeSelf) reportMessagePanelExitButton.onClick.Invoke();
else if (editMessagePanelCurrent != null) editMessagePanelCurrent.transform.GetChild(0).GetChild(0).GetComponent<Button>().onClick.Invoke();
else await SceneManager.LoadSceneAsync("MainMenu");
}
}
IEnumerator ScrollToBottom()
{
yield return new WaitForEndOfFrame();
content.transform.localPosition = new UnityEngine.Vector2(0f, content.GetComponent<RectTransform>().sizeDelta.y);
}
void OptionsButtonClick(ChatroomMessage message, BigInteger localUserId)
{
selectedMessageForOptions = message;
optionsPanelDeleteButton.transform.parent.gameObject.SetActive(localUserId != 0 && message.UserID == localUserId);
optionsPanelEditButton.transform.parent.gameObject.SetActive(localUserId != 0 && message.UserID == localUserId);
optionsPanelReportButton.transform.parent.gameObject.SetActive(localUserId != 0 && message.UserID != localUserId);
optionsPanel.SetActive(true);
}
}