Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PORT] Nanochat #1009

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Content.Client/Access/UI/AgentIDCardBoundUserInterface.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,16 @@ protected override void Open()
_window.OnNameChanged += OnNameChanged;
_window.OnJobChanged += OnJobChanged;
_window.OnJobIconChanged += OnJobIconChanged;
_window.OnNumberChanged += OnNumberChanged; // Corvax-Next-PDAChat
}

// Corvax-Next-PDAChat-Start
private void OnNumberChanged(uint newNumber)
{
SendMessage(new AgentIDCardNumberChangedMessage(newNumber));
}
// Corvax-Next-PDAChat-End

private void OnNameChanged(string newName)
{
SendMessage(new AgentIDCardNameChangedMessage(newName));
Expand Down Expand Up @@ -56,6 +64,7 @@ protected override void UpdateState(BoundUserInterfaceState state)
_window.SetCurrentName(cast.CurrentName);
_window.SetCurrentJob(cast.CurrentJob);
_window.SetAllowedIcons(cast.CurrentJobIconId);
_window.SetCurrentNumber(cast.CurrentNumber); // Corvax-Next-PDAChat
}
}
}
4 changes: 4 additions & 0 deletions Content.Client/Access/UI/AgentIDCardWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
<LineEdit Name="NameLineEdit" />
<Label Name="CurrentJob" Text="{Loc 'agent-id-card-current-job'}" />
<LineEdit Name="JobLineEdit" />
<!-- Corvax-Next-PDAChat-Start - Add NanoChat number field -->
<Label Name="CurrentNumber" Text="{Loc 'agent-id-card-current-number'}" />
<LineEdit Name="NumberLineEdit" PlaceHolder="#0000" />
<!-- Corvax-Next-PDAChat-End- -->
<Label Text="{Loc 'agent-id-card-job-icon-label'}"/>
<GridContainer Name="IconGrid" Columns="10">
<!-- Job icon buttons are generated in the code -->
Expand Down
37 changes: 37 additions & 0 deletions Content.Client/Access/UI/AgentIDCardWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,13 @@ public sealed partial class AgentIDCardWindow : DefaultWindow
private readonly SpriteSystem _spriteSystem;

private const int JobIconColumnCount = 10;

private const int MaxNumberLength = 4; // Corvax-Next-PDAChat - Same as NewChatPopup
Comment on lines +23 to +24
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Вынести дублирующуюся константу!

Константа MaxNumberLength дублируется с NewChatPopup. Рекомендуется вынести её в общий файл констант.


public event Action<string>? OnNameChanged;
public event Action<string>? OnJobChanged;

public event Action<uint>? OnNumberChanged; // Corvax-Next-PDAChat - Add event for number changes

public event Action<ProtoId<JobIconPrototype>>? OnJobIconChanged;

Expand All @@ -35,9 +39,42 @@ public AgentIDCardWindow()
NameLineEdit.OnTextEntered += e => OnNameChanged?.Invoke(e.Text);
NameLineEdit.OnFocusExit += e => OnNameChanged?.Invoke(e.Text);

// Corvax-Next-PDAChat-Start
JobLineEdit.OnTextEntered += e => OnJobChanged?.Invoke(e.Text);
JobLineEdit.OnFocusExit += e => OnJobChanged?.Invoke(e.Text);

// Corvax-Next-PDAChat - Add handlers for number changes
NumberLineEdit.OnTextEntered += OnNumberEntered;
NumberLineEdit.OnFocusExit += OnNumberEntered;

// Corvax-Next-PDAChat - Filter to only allow digits
NumberLineEdit.OnTextChanged += args =>
{
if (args.Text.Length > MaxNumberLength)
{
NumberLineEdit.Text = args.Text[..MaxNumberLength];
}

// Filter to digits only
var newText = string.Concat(args.Text.Where(char.IsDigit));
if (newText != args.Text)
NumberLineEdit.Text = newText;
};
}

// Corvax-Next-PDAChat - Add number validation and event
private void OnNumberEntered(LineEdit.LineEditEventArgs args)
{
if (uint.TryParse(args.Text, out var number) && number > 0)
OnNumberChanged?.Invoke(number);
}

// Corvax-Next-PDAChat - Add setter for current number
public void SetCurrentNumber(uint? number)
{
NumberLineEdit.Text = number?.ToString("D4") ?? "";
}
// Corvax-Next-PDAChat-End

public void SetAllowedIcons(string currentJobIconId)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<BoxContainer
xmlns="https://spacestation14.io"
xmlns:graphics="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
HorizontalExpand="True">
<Button Name="ChatButton"
StyleClasses="ButtonSquare"
HorizontalExpand="True"
MaxSize="137 64"
Margin="0 1">
<BoxContainer Orientation="Horizontal"
HorizontalExpand="True"
VerticalExpand="True"
MinWidth="132"
Margin="6 4"
VerticalAlignment="Center">
<!-- Unread indicator dot -->
<PanelContainer Name="UnreadIndicator"
MinSize="8 8"
MaxSize="8 8"
VerticalAlignment="Center"
Margin="0 0 6 0">
<PanelContainer.PanelOverride>
<graphics:StyleBoxFlat
BackgroundColor="#17c622"
BorderColor="#0f7a15" />
</PanelContainer.PanelOverride>
</PanelContainer>

<!-- Text container -->
<BoxContainer Orientation="Vertical"
HorizontalExpand="True"
VerticalExpand="True"
VerticalAlignment="Center">
<RichTextLabel Name="NameLabel"
StyleClasses="LabelHeading"
HorizontalExpand="True"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="0 -2 0 0" />
<Label Name="JobLabel"
StyleClasses="LabelSubText"
HorizontalExpand="True"
ClipText="False"
HorizontalAlignment="Center" />
</BoxContainer>
</BoxContainer>
</Button>
</BoxContainer>
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using Content.Shared._CorvaxNext.CartridgeLoader.Cartridges;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;

namespace Content.Client._CorvaxNext.CartridgeLoader.Cartridges;

[GenerateTypedNameReferences]
public sealed partial class NanoChatEntry : BoxContainer
{
public event Action<uint>? OnPressed;
private uint _number;
private Action<EventArgs>? _pressHandler;

public NanoChatEntry()
{
RobustXamlLoader.Load(this);
}

public void SetRecipient(NanoChatRecipient recipient, uint number, bool isSelected)
{
// Remove old handler if it exists
if (_pressHandler != null)
ChatButton.OnPressed -= _pressHandler;

_number = number;

// Create and store new handler
_pressHandler = _ => OnPressed?.Invoke(_number);
ChatButton.OnPressed += _pressHandler;

NameLabel.Text = recipient.Name;
JobLabel.Text = recipient.JobTitle ?? "";
JobLabel.Visible = !string.IsNullOrEmpty(recipient.JobTitle);
UnreadIndicator.Visible = recipient.HasUnread;

ChatButton.ModulateSelfOverride = isSelected ? NanoChatMessageBubble.OwnMessageColor : null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<BoxContainer xmlns="https://spacestation14.io"
xmlns:customControls="clr-namespace:Content.Client.Administration.UI.CustomControls"
Margin="4"
Orientation="Vertical">
<BoxContainer Orientation="Horizontal">
<Label Name="NumberLabel"
Align="Right"
SetWidth="26"
ClipText="True" />
<Label Name="TimeLabel"
Align="Center"
SetWidth="100"
ClipText="True" />
<Label Name="MessageLabel"
Align="Left"
MinWidth="390"
HorizontalExpand="True"
ClipText="False" />
</BoxContainer>
<customControls:HSeparator Margin="0 5 0 5" />
</BoxContainer>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;

namespace Content.Client._CorvaxNext.CartridgeLoader.Cartridges;

[GenerateTypedNameReferences]
public sealed partial class NanoChatLogEntry : BoxContainer
{
public NanoChatLogEntry(int number, string time, string message)
{
RobustXamlLoader.Load(this);
NumberLabel.Text = number.ToString();
TimeLabel.Text = time;
MessageLabel.Text = message;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<cartridges:NanoChatMessageBubble
xmlns="https://spacestation14.io"
xmlns:cartridges="clr-namespace:Content.Client._CorvaxNext.CartridgeLoader.Cartridges"
xmlns:graphics="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
HorizontalExpand="True">

<BoxContainer Name="MessageContainer"
Orientation="Horizontal"
HorizontalExpand="True">
<!-- Left spacer for other's messages -->
<Control Name="LeftSpacer"
MinSize="12 0" />

<!-- Message panel -->
<BoxContainer Name="MessageBox"
Orientation="Vertical"
MaxWidth="320"
HorizontalExpand="True">
<PanelContainer Name="MessagePanel"
MaxWidth="320"
HorizontalExpand="True">
<PanelContainer.PanelOverride>
<graphics:StyleBoxFlat
ContentMarginLeftOverride="10"
ContentMarginRightOverride="10"
ContentMarginTopOverride="6"
ContentMarginBottomOverride="6"
BorderThickness="1">
<!-- Colors set in code based on message sender -->
</graphics:StyleBoxFlat>
</PanelContainer.PanelOverride>

<RichTextLabel Name="MessageText"
HorizontalExpand="True" />
</PanelContainer>

<!-- Delivery failed text -->
<Label Name="DeliveryFailedLabel"
Text="{Loc nano-chat-delivery-failed}"
StyleClasses="LabelSmall"
HorizontalExpand="True"
HorizontalAlignment="Right"
Margin="10 2 10 0"
Visible="False" />
</BoxContainer>

<!-- Right spacer for own messages -->
<Control Name="RightSpacer"
MinSize="12 0" />

<!-- Flexible space for alignment -->
<Control Name="FlexSpace"
HorizontalExpand="True" />
</BoxContainer>
</cartridges:NanoChatMessageBubble>
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using Content.Shared._CorvaxNext.CartridgeLoader.Cartridges;
using Robust.Client.AutoGenerated;
using Robust.Client.Graphics;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;

namespace Content.Client._CorvaxNext.CartridgeLoader.Cartridges;

[GenerateTypedNameReferences]
public sealed partial class NanoChatMessageBubble : BoxContainer
{
public static readonly Color OwnMessageColor = Color.FromHex("#173717d9"); // Dark green
public static readonly Color OtherMessageColor = Color.FromHex("#252525d9"); // Dark gray
public static readonly Color BorderColor = Color.FromHex("#40404066"); // Subtle border
public static readonly Color TextColor = Color.FromHex("#dcdcdc"); // Slightly softened white
public static readonly Color ErrorColor = Color.FromHex("#cc3333"); // Red
Comment on lines +12 to +16
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Переместите цвета в систему тем

Жестко закодированные значения цветов следует перенести в систему тем для обеспечения единообразия и поддержки различных тем оформления.

-public static readonly Color OwnMessageColor = Color.FromHex("#173717d9");
-public static readonly Color OtherMessageColor = Color.FromHex("#252525d9");
-public static readonly Color BorderColor = Color.FromHex("#40404066");
-public static readonly Color TextColor = Color.FromHex("#dcdcdc");
-public static readonly Color ErrorColor = Color.FromHex("#cc3333");
+public static readonly string ThemeVarOwnMessage = "nanochat-own-message";
+public static readonly string ThemeVarOtherMessage = "nanochat-other-message";
// ... и так далее для остальных цветов

Committable suggestion skipped: line range outside the PR's diff.


public NanoChatMessageBubble()
{
RobustXamlLoader.Load(this);
}

public void SetMessage(NanoChatMessage message, bool isOwnMessage)
{
if (MessagePanel.PanelOverride is not StyleBoxFlat)
return;

// Configure message appearance
var style = (StyleBoxFlat)MessagePanel.PanelOverride;
style.BackgroundColor = isOwnMessage ? OwnMessageColor : OtherMessageColor;
style.BorderColor = BorderColor;

// Set message content
MessageText.Text = message.Content;
MessageText.Modulate = TextColor;

// Show delivery failed text if needed (only for own messages)
DeliveryFailedLabel.Visible = isOwnMessage && message.DeliveryFailed;
if (DeliveryFailedLabel.Visible)
DeliveryFailedLabel.Modulate = ErrorColor;

// For own messages: FlexSpace -> MessagePanel -> RightSpacer
// For other messages: LeftSpacer -> MessagePanel -> FlexSpace
MessageContainer.RemoveAllChildren();

// fuuuuuck
MessageBox.Parent?.RemoveChild(MessageBox);

if (isOwnMessage)
{
MessageContainer.AddChild(FlexSpace);
MessageContainer.AddChild(MessageBox);
MessageContainer.AddChild(RightSpacer);
}
else
{
MessageContainer.AddChild(LeftSpacer);
MessageContainer.AddChild(MessageBox);
MessageContainer.AddChild(FlexSpace);
}
}
}
43 changes: 43 additions & 0 deletions Content.Client/Backmen/CartridgeLoader/Cartridges/NanoChatUi.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using Content.Client.UserInterface.Fragments;
using Content.Shared.CartridgeLoader;
using Content.Shared._CorvaxNext.CartridgeLoader.Cartridges;
using Robust.Client.UserInterface;

namespace Content.Client._CorvaxNext.CartridgeLoader.Cartridges;

public sealed partial class NanoChatUi : UIFragment
{
private NanoChatUiFragment? _fragment;

public override Control GetUIFragmentRoot()
{
return _fragment!;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Добавьте проверку на null

Использование оператора ! может привести к исключению NullReferenceException. Рекомендуется добавить явную проверку.

-        return _fragment!;
+        if (_fragment == null)
+            throw new InvalidOperationException("NanoChatUi fragment not initialized");
+        return _fragment;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return _fragment!;
if (_fragment == null)
throw new InvalidOperationException("NanoChatUi fragment not initialized");
return _fragment;

}

public override void Setup(BoundUserInterface userInterface, EntityUid? fragmentOwner)
{
_fragment = new NanoChatUiFragment();

_fragment.OnMessageSent += (type, number, content, job) =>
{
SendNanoChatUiMessage(type, number, content, job, userInterface);
};
}

public override void UpdateState(BoundUserInterfaceState state)
{
if (state is NanoChatUiState cast)
_fragment?.UpdateState(cast);
}

private static void SendNanoChatUiMessage(NanoChatUiMessageType type,
uint? number,
string? content,
string? job,
BoundUserInterface userInterface)
{
var nanoChatMessage = new NanoChatUiMessageEvent(type, number, content, job);
var message = new CartridgeUiMessage(nanoChatMessage);
userInterface.SendMessage(message);
}
}
Loading
Loading