Editor/AllChatWindow.cs
using Editor;
using Sandbox;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
namespace EditorAllChat;
[Dock( "Editor", "All Chat", "chat" )]
public class AllChatWindow : Widget
{
public static string API_URL => "http://allchat.carsonk.net:2222";
public static string WEBSOCKET_URL => "ws://allchat.carsonk.net:2222";
public static string ADMIN_PASSWORD = "";
ScrollArea ScrollArea;
LineEdit LineEdit;
MessageObject LastMessage;
WebSocket WebSocket;
CancellationTokenSource CancellationTokenSource;
public AllChatWindow( Widget parent ) : base( parent )
{
Layout = Layout.Column();
ADMIN_PASSWORD = EditorCookie.GetString( "allchat_admin_password", "" );
Width = 300;
Height = 450;
ScrollArea = Layout.Add( new ScrollArea( this ) );
ScrollArea.Canvas = new Widget();
ScrollArea.Canvas.Layout = Layout.Column();
ScrollArea.Canvas.Layout.Spacing = 2;
ScrollArea.Canvas.Layout.Margin = new Sandbox.UI.Margin( 0, 0, 0, 8 );
ScrollArea.Canvas.Layout.AddStretchCell();
LineEdit = Layout.Add( new LineEdit() );
LineEdit.PlaceholderText = "Type a message and press Enter...";
LineEdit.ReturnPressed += SendMessage;
// Button to open additional chat window for testing
//var button = Layout.Add( new Button( "Open Another Chat Widget" ) );
//button.Clicked += () =>
//{
// var newWindow = new AllChatWindow( null );
// newWindow.Show();
//};
Init();
}
async void Init()
{
CancellationTokenSource = new CancellationTokenSource();
WebSocket = new WebSocket();
WebSocket.OnMessageReceived += OnWebsocketMessage;
await WebSocket.Connect( WEBSOCKET_URL, CancellationTokenSource.Token );
}
void OnWebsocketMessage( string message )
{
var eventData = Json.Deserialize<StreamObject>( message );
switch ( eventData.Type )
{
case "connected":
break;
case "new_message":
var newMsg = eventData.Data.Deserialize<MessageObject>();
if ( newMsg is not null )
{
AddMessage( newMsg );
}
break;
case "message_deleted":
var deletedId = eventData.Data["id"].ToString();
foreach ( var child in ScrollArea.Canvas.Children )
{
if ( child is MessageWidget msgWidget && msgWidget?.Message?.IdString == deletedId )
{
msgWidget?.Destroy();
break;
}
}
break;
case "messages_cleared":
foreach ( var child in ScrollArea.Canvas.Children )
{
child?.Destroy();
}
break;
case "message_history":
var jsonArray = eventData.Data.AsArray();
if ( jsonArray is not null )
{
foreach ( var item in jsonArray )
{
var msg = item.Deserialize<MessageObject>();
if ( msg is not null )
{
AddMessage( msg );
}
}
}
break;
}
}
public void Disconnect()
{
CancellationTokenSource?.Cancel();
WebSocket?.Dispose();
WebSocket = null;
}
async void SendMessage()
{
if ( string.IsNullOrEmpty( LineEdit.Text ) )
return;
var msg = LineEdit.Text;
LineEdit.Text = "";
var sent = new SentMessage
{
Message = msg,
SteamId = Game.SteamId.ValueUnsigned
};
var response = await Http.RequestJsonAsync<MessageResponse>( API_URL + "/message", "POST", Http.CreateJsonContent( sent ) );
//if ( response?.Success == true )
//{
// AddMessage( response.Data );
//}
}
public async void AddMessage( MessageObject message )
{
// If the new timestamp is on a different day than the last message, add a day header
if ( LastMessage == null || LastMessage.Timestamp.Date != message.Timestamp.Date )
{
ScrollArea.Canvas.Layout.Add( new DayHeader( message.Timestamp.Date ) );
}
var fullyScrolled = (ScrollArea.VerticalScrollbar.SliderPosition >= ScrollArea.VerticalScrollbar.Maximum - 1);
var msgWidget = new MessageWidget( message );
ScrollArea.Canvas.Layout.Add( msgWidget );
LastMessage = message;
await Task.Delay( 25 );
if ( fullyScrolled || message.SteamId == Game.SteamId )
{
ScrollArea.MakeVisible( msgWidget );
}
}
protected override bool OnClose()
{
Disconnect();
return base.OnClose();
}
public override void OnDestroyed()
{
Disconnect();
base.OnDestroyed();
}
[Shortcut( "gameObject.align-to-view", "CTRL+SHIFT+F" )]
void OpenAdminPrompt()
{
var dialog = new Dialog();
dialog.Layout = Layout.Column();
dialog.Window.Title = "Admin Login";
dialog.Window.Width = 300;
dialog.Window.Height = 150;
// Prompt for admin password
var passwordInput = dialog.Layout.Add( new LineEdit() );
passwordInput.PlaceholderText = "Admin Password";
// Submit Button
var submitButton = dialog.Layout.Add( new Button( "Submit" ) );
submitButton.Clicked += () =>
{
ADMIN_PASSWORD = passwordInput.Text;
EditorCookie.SetString( "allchat_admin_password", ADMIN_PASSWORD );
dialog?.Close();
};
dialog.Show();
}
}