using System;
using System.Collections.Generic;
using BestHTTP.Examples.Helpers;
using BestHTTP.SocketIO3;
using BestHTTP.SocketIO3.Events;
using UnityEngine;
using UnityEngine.UI;
namespace BestHTTP.Examples.SocketIO3
{
#pragma warning disable 0649
[PlatformSupport.IL2CPP.Preserve]
class LoginData
{
[PlatformSupport.IL2CPP.Preserve] public int numUsers;
}
[PlatformSupport.IL2CPP.Preserve]
sealed class NewMessageData
{
[PlatformSupport.IL2CPP.Preserve] public string username;
[PlatformSupport.IL2CPP.Preserve] public string message;
}
[PlatformSupport.IL2CPP.Preserve]
sealed class UserJoinedData : LoginData
{
[PlatformSupport.IL2CPP.Preserve] public string username;
}
[PlatformSupport.IL2CPP.Preserve]
sealed class TypingData
{
[PlatformSupport.IL2CPP.Preserve] public string username;
}
#pragma warning restore
public sealed class ChatSample : BestHTTP.Examples.Helpers.SampleBase
{
private readonly TimeSpan TYPING_TIMER_LENGTH = TimeSpan.FromMilliseconds(700);
#pragma warning disable 0649, 0414
[SerializeField]
[Tooltip("The Socket.IO service address to connect to")]
private string address = "https://socket-io-3-chat-5ae3v.ondigitalocean.app";
[Header("Login Details")]
[SerializeField]
private RectTransform _loginRoot;
[SerializeField]
private InputField _userNameInput;
[Header("Chat Setup")]
[SerializeField]
private RectTransform _chatRoot;
[SerializeField]
private Text _participantsText;
[SerializeField]
private ScrollRect _scrollRect;
[SerializeField]
private RectTransform _contentRoot;
[SerializeField]
private TextListItem _listItemPrefab;
[SerializeField]
private int _maxListItemEntries = 100;
[SerializeField]
private Text _typingUsersText;
[SerializeField]
private InputField _input;
[Header("Buttons")]
[SerializeField]
private Button _connectButton;
[SerializeField]
private Button _closeButton;
#pragma warning restore
///
/// The Socket.IO manager instance.
///
private SocketManager Manager;
///
/// True if the user is currently typing
///
private bool typing;
///
/// When the message changed.
///
private DateTime lastTypingTime = DateTime.MinValue;
///
/// Users that typing.
///
private List typingUsers = new List();
#region Unity Events
protected override void Start()
{
base.Start();
this._userNameInput.text = PlayerPrefs.GetString("SocketIO3ChatSample_UserName");
SetButtons(!string.IsNullOrEmpty(this._userNameInput.text), false);
SetPanels(true);
}
void OnDestroy()
{
if (this.Manager != null)
{
// Leaving this sample, close the socket
this.Manager.Close();
this.Manager = null;
}
}
public void OnUserNameInputChanged(string userName)
{
SetButtons(!string.IsNullOrEmpty(userName), false);
}
public void OnUserNameInputSubmit(string userName)
{
if (Input.GetKeyDown(KeyCode.KeypadEnter) || Input.GetKeyDown(KeyCode.Return))
OnConnectButton();
}
public void UpdateTyping()
{
if (!typing)
{
typing = true;
Manager.Socket.Emit("typing");
}
lastTypingTime = DateTime.UtcNow;
}
public void OnMessageInput(string textToSend)
{
if ((!Input.GetKeyDown(KeyCode.KeypadEnter) && !Input.GetKeyDown(KeyCode.Return)) || string.IsNullOrEmpty(textToSend))
return;
Manager.Socket.Emit("new message", textToSend);
AddText(string.Format("{0}: {1}", this._userNameInput.text, textToSend));
}
public void OnConnectButton()
{
SetPanels(false);
PlayerPrefs.SetString("SocketIO3ChatSample_UserName", this._userNameInput.text);
AddText("Connecting...");
// Create the Socket.IO manager
Manager = new SocketManager(new Uri(this.address));
Manager.Socket.On(SocketIOEventTypes.Connect, OnConnected);
Manager.Socket.On(SocketIOEventTypes.Disconnect, OnDisconnected);
Manager.Socket.On("login", OnLogin);
Manager.Socket.On("new message", OnNewMessage);
Manager.Socket.On("user joined", OnUserJoined);
Manager.Socket.On("user left", OnUserLeft);
Manager.Socket.On("typing", OnTyping);
Manager.Socket.On("stop typing", OnStopTyping);
SetButtons(false, true);
}
public void OnCloseButton()
{
SetButtons(false, false);
this.Manager.Close();
}
void Update()
{
if (typing)
{
var typingTimer = DateTime.UtcNow;
var timeDiff = typingTimer - lastTypingTime;
if (timeDiff >= TYPING_TIMER_LENGTH)
{
Manager.Socket.Emit("stop typing");
typing = false;
}
}
}
#endregion
#region SocketIO Events
private void OnConnected(ConnectResponse resp)
{
AddText("Connected! Socket.IO SID: " + resp.sid);
Manager.Socket.Emit("add user", this._userNameInput.text);
this._input.interactable = true;
}
private void OnDisconnected()
{
AddText("Disconnected!");
SetPanels(true);
SetButtons(true, false);
}
private void OnLogin(LoginData data)
{
AddText("Welcome to Socket.IO Chat");
if (data.numUsers == 1)
this._participantsText.text = "there's 1 participant";
else
this._participantsText.text = "there are " + data.numUsers + " participants";
}
private void OnNewMessage(NewMessageData data)
{
AddText(string.Format("{0}: {1}", data.username, data.message));
}
private void OnUserJoined(UserJoinedData data)
{
AddText(string.Format("{0} joined", data.username));
if (data.numUsers == 1)
this._participantsText.text = "there's 1 participant";
else
this._participantsText.text = "there are " + data.numUsers + " participants";
}
private void OnUserLeft(UserJoinedData data)
{
AddText(string.Format("{0} left", data.username));
if (data.numUsers == 1)
this._participantsText.text = "there's 1 participant";
else
this._participantsText.text = "there are " + data.numUsers + " participants";
}
private void OnTyping(TypingData data)
{
int idx = typingUsers.FindIndex((name) => name.Equals(data.username));
if (idx == -1)
typingUsers.Add(data.username);
SetTypingUsers();
}
private void OnStopTyping(TypingData data)
{
int idx = typingUsers.FindIndex((name) => name.Equals(data.username));
if (idx != -1)
typingUsers.RemoveAt(idx);
SetTypingUsers();
}
#endregion
private void AddText(string text)
{
GUIHelper.AddText(this._listItemPrefab, this._contentRoot, text, this._maxListItemEntries, this._scrollRect);
}
private void SetTypingUsers()
{
if (this.typingUsers.Count > 0)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder(this.typingUsers[0], this.typingUsers.Count + 1);
for (int i = 1; i < this.typingUsers.Count; ++i)
sb.AppendFormat(", {0}", this.typingUsers[i]);
if (this.typingUsers.Count == 1)
sb.Append(" is typing!");
else
sb.Append(" are typing!");
this._typingUsersText.text = sb.ToString();
}
else
this._typingUsersText.text = string.Empty;
}
private void SetPanels(bool login)
{
if (login)
{
this._loginRoot.gameObject.SetActive(true);
this._chatRoot.gameObject.SetActive(false);
this._input.interactable = false;
}
else
{
this._loginRoot.gameObject.SetActive(false);
this._chatRoot.gameObject.SetActive(true);
this._input.interactable = true;
}
}
private void SetButtons(bool connect, bool close)
{
if (this._connectButton != null)
this._connectButton.interactable = connect;
if (this._closeButton != null)
this._closeButton.interactable = close;
}
}
}