UI/Chat/Chat.razor
@using Sandbox.UI
@inherits Panel
<style>
Chat {
position: absolute;
bottom: 48px;
left: 80px;
width: 550px;
flex-direction: column;
gap: 12px;
.output {
flex-direction: column;
max-height: 520px;
overflow: hidden;
padding: 12px 14px;
background-color: rgba(0, 0, 0, 0.24);
border-left: 2px solid rgba(120, 220, 255, 0.28);
border-right: 2px solid rgba(120, 220, 255, 0.28);
}
.chat_entry {
flex-direction: row;
gap: 10px;
margin-bottom: 6px;
text-shadow: 0 2px 2px rgba(0, 0, 0, 0.85);
.author {
color: #5ec8ff;
font-family: "AzeretMono-Medium";
font-size: 22px;
}
.message {
color: white;
font-family: "AzeretMono-Medium";
font-size: 22px;
}
}
.input {
opacity: 0;
pointer-events: none;
transition: opacity 0.08s ease;
}
.input TextEntry {
background-color: rgba(0, 0, 0, 0.6);
color: white;
font-family: "AzeretMono-Medium";
font-size: 24px;
padding: 14px 16px;
border-left: 2px solid rgba(120, 220, 255, 0.35);
border-right: 2px solid rgba(120, 220, 255, 0.35);
}
&.open .input {
opacity: 1;
pointer-events: all;
}
}
</style>
<root>
@if ( _entries.Count > 0 )
{
<div class="output">
@foreach ( var entry in _entries )
{
<div class="chat_entry">
<div class="author">@entry.Author:</div>
<div class="message">@entry.Message</div>
</div>
}
</div>
}
<div class="input">
<TextEntry @ref="_textEntry" onsubmit="@OnSubmit" />
</div>
</root>
@code
{
private TextEntry _textEntry;
private readonly List<Entry> _entries = new();
private bool _chatActive;
protected override void OnAfterTreeRender( bool firstTime )
{
base.OnAfterTreeRender( firstTime );
if ( !firstTime ) return;
ChatEvent.OnChat += AddEntry;
}
public override void OnDeleted()
{
ChatEvent.OnChat -= AddEntry;
}
private readonly record struct Entry( string Author, string Message, RealTimeSince Age );
private void OnSubmit()
{
var msg = _textEntry?.Text?.Trim();
if ( _textEntry != null ) _textEntry.Text = string.Empty;
if ( !string.IsNullOrWhiteSpace( msg ) )
{
ConsoleSystem.Run( "fp4_chat", msg );
}
_chatActive = false;
_textEntry?.Blur();
}
public override void Tick()
{
base.Tick();
if ( _textEntry == null )
return;
if ( Input.Pressed( "Chat" ) || Input.Pressed( "chat" ) )
{
_chatActive = true;
}
if ( _chatActive && Input.Pressed( "menu" ) )
{
_chatActive = false;
_textEntry?.Blur();
}
if ( _chatActive && !_textEntry.HasFocus )
{
_textEntry.Focus();
}
if ( _entries.RemoveAll( x => x.Age > 20f ) > 0 )
StateHasChanged();
SetClass( "open", _chatActive );
}
public void AddEntry( string name, string message )
{
if ( string.IsNullOrWhiteSpace( message ) )
return;
_entries.Add( new Entry( name, message, 0f ) );
StateHasChanged();
}
}