sasalka/Code/UI/Chat.razor
2025-06-08 23:47:32 +03:00

139 lines
2.6 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@using System;
@using Sandbox.UI;
@namespace Sandbox
@inherits PanelComponent
@implements Component.INetworkListener
<root>
<div class="output">
@foreach (var entry in Entries)
{
<div class="chat_entry">
@if (entry.steamid > 0)
{
<div class="avatar" style="background-image: url( avatar:@entry.steamid )"></div>
}
<div class="author">@entry.author</div>
<div class="message">@entry.message</div>
</div>
}
</div>
<div class="input">
<TextEntry @ref="InputBox" onsubmit="@ChatFinished"></TextEntry>
</div>
</root>
@code
{
public static Chat Instance;
public Chat() => Instance = this;
public static bool IsActive => Instance.InputBox.HasFocus;
public static void Open()
{
Instance.InputBox.Focus();
}
public static void AddText(string text)
{
Instance.AddTextInternal(text);
}
public event Action<string> OnChat;
public TextEntry InputBox;
public record Entry(ulong steamid, string author, string message, RealTimeSince timeSinceAdded);
List<Entry> Entries = new();
protected override void OnUpdate()
{
if (InputBox is null)
return;
Panel.AcceptsFocus = false;
if (Input.Pressed("chat"))
Open();
if (Entries.RemoveAll(x => x.timeSinceAdded > 20.0f) > 0)
{
StateHasChanged();
}
if (InputBox.HasFocus && Input.EscapePressed)
{
Input.EscapePressed = false;
ChatClosed();
}
SetClass("open", InputBox.HasFocus);
}
void ChatFinished()
{
var text = InputBox.Text;
Mouse.Visibility = MouseVisibility.Auto;
OnChat?.Invoke(text);
OnChat = null;
if (string.IsNullOrWhiteSpace(text))
return;
AddTextInternal(InputBox.Text);
InputBox.Text = "";
}
void ChatClosed()
{
var text = InputBox.Text;
InputBox.Text = "";
OnChat = null;
}
[Rpc.Broadcast]
public void AddTextInternal(string message)
{
message = message.Truncate(300);
if (string.IsNullOrWhiteSpace(message))
return;
var author = Rpc.Caller.DisplayName;
var steamid = Rpc.Caller.SteamId;
Log.Info($"{author}: {message}");
Entries.Add(new Entry(steamid, author, message, 0.0f));
StateHasChanged();
}
[Rpc.Broadcast]
void AddSystemText(string message)
{
message = message.Truncate(300);
if (string.IsNullOrWhiteSpace(message))
return;
Entries.Add(new Entry(0, "", message, 0.0f));
StateHasChanged();
}
void Component.INetworkListener.OnConnected(Connection channel)
{
if (IsProxy) return;
AddSystemText($"{channel.DisplayName} has joined the game");
}
void Component.INetworkListener.OnDisconnected(Connection channel)
{
if (IsProxy) return;
AddSystemText($"{channel.DisplayName} has left the game");
}
}