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] NanoСhat #1055

Merged
merged 5 commits into from
Feb 16, 2025
Merged

[PORT] NanoСhat #1055

merged 5 commits into from
Feb 16, 2025

Conversation

CatBackGround
Copy link
Contributor

@CatBackGround CatBackGround commented Feb 15, 2025

Описание PR

Порт NanoChat, ведь Тресту было лень фиксить свой PR.
Оригинальный PR - space-syndicate/space-station-14-next#153

Медиа

Soon...

Тип PR

  • Feature
  • Fix
  • Tweak
  • Balance
  • Refactor
  • Port
  • Translate
  • Resprite

Изменения

🆑 CatBG

  • add: Добавлен NanoChat, как один из способов коммуникации между экипажем.

Summary by CodeRabbit

  • Новые возможности

    • Внедрён полноценный интерфейс NanoChat: чат с созданием, отправкой и управлением сообщениями, а также настройка уведомлений.
    • Обновлён интерфейс удостоверения агента – теперь отображается текущий NanoChat номер.
    • Расширена интеграция NanoChat с устройствами (PDA, идентификационные карты).
  • Локализация

    • Добавлены и обновлены строки для элементов NanoChat и агентских удостоверений на английском и русском языках.

@CatBackGround CatBackGround requested a review from Rxup as a code owner February 15, 2025 09:46
Copy link
Contributor

coderabbitai bot commented Feb 15, 2025

Walkthrough

В этом обновлении добавлена интеграция NanoChat в различные подсистемы: изменена логика работы агентских ID-карт для отслеживания номера, расширен интерфейс NanoChat с новыми элементами ввода и отображения сообщений, а также внедрены новые серверные системы для обработки и передачи данных NanoChat. Изменения затрагивают как клиентскую, так и серверную части, а также обновления локализации, прототипов и метаданных визуальных компонентов.

Changes

Файл / Группа Изменения
AgentIDCard UI
(AgentIDCardBoundUserInterface.cs, AgentIDCardWindow.xaml, AgentIDCardWindow.xaml.cs)
Добавлен обработчик события OnNumberChanged и метод отправки AgentIDCardNumberChangedMessage; обновлён метод UpdateState для обновления текущего номера; добавлены новые элементы управления (Label и LineEdit) для ввода NanoChat номера.
LogProbe UI
(LogProbeUi.cs, LogProbeUiFragment.xaml, LogProbeUiFragment.xaml.cs)
Изменена логика обновления состояния UI с передачей полного объекта состояния вместо части данных; реорганизована компоновка элементов (изменён BoxContainer, добавлены TitleLabel и CardNumberLabel); добавлена поддержка NanoChatData для отображения соответствующих данных.
NanoChat UI компоненты
(NanoChatEntry.xaml/.cs, NanoChatLogEntry.xaml/.cs, NanoChatMessageBubble.xaml/.cs, NanoChatUi.cs, NanoChatUiFragment.xaml/.cs, NewChatPopup.xaml/.cs)
Введены новые компоненты для отображения записей чата, логов сообщений и пузырьков сообщений; добавлен обработчик событий для отправки и валидации сообщений; реализовано окно создания нового чата с валидацией и сбросом ввода; обновлён принцип работы UI для поддержки динамического отображения и управления чатами.
NanoChat система
(NanoChatSystem.cs – клиентский и серверный, LogProbeCartridgeSystem.NanoChat.cs, NanoChatCartridgeComponent.cs, NanoChatCartridgeSystem.cs, SharedNanoChatSystem.cs, NanoChatUiMessageEvent.cs, NanoChatUiState.cs, NanoChatCardComponent.cs)
Добавлена функциональность NanoChat: управление номерами, отправкой и получением сообщений; интеграция с агентскими ID-картами и LogProbe системами; расширенные методы обновления UI и обработки событий NanoChat; добавлены новые классы и структуры для обмена сообщениями, управления получателями и уведомлениями.
Локализация
(файлы в Resources/Locale/en-US и ru-RU)
Добавлены новые строки для NanoChat (названия, подсказки, уведомления) и для отображения NanoChat номера в агентских ID-картах; обновлены существующие строки для поддержки новых функций.
Прототипы и метаданные
(pda.yml, identification_cards.yml, cartridges.yml, name_identifier_groups.yml, meta.json)
Добавлен новый компонент NanoChatCartridge в PDA и идентификационные карты; внесены изменения в прототипы для поддержки NanoChat; добавлены метаданные и визуальные ресурсы для NanoChatCartridge; обновлены настройки групп идентификаторов для NanoChat.
Прочее
(файлы ATTRIBUTION.txt, disease.ftl, swab.ftl)
Небольшие изменения – комментарии, атрибуция и форматирование в файлах локализации, не влияющие на функциональность.

Sequence Diagram(s)

sequenceDiagram
    participant Пользователь
    participant UI as NanoChatUiFragment
    participant NanoChatUi
    participant Server as NanoChatCartridgeSystem
    participant Shared as SharedNanoChatSystem

    Пользователь->>UI: Ввод сообщения
    UI->>NanoChatUi: Генерация события OnMessageSent
    NanoChatUi->>Server: Вызов SendNanoChatUiMessage(тип, номер, содержимое, должность)
    Server->>Shared: Обработка и доставка сообщения
    Shared-->>Server: Результат обработки
    Server->>UI: Обновление состояния (UpdateState с новыми сообщениями)
    UI->>Пользователь: Отображение обновлённого чата
Loading
sequenceDiagram
    participant Пользователь
    participant AID_UI as AgentIDCardWindow
    participant AID_BUI as AgentIDCardBoundUserInterface
    participant Server as AgentIDCardSystem
    participant NanoChat as NanoChatCardComponent

    Пользователь->>AID_UI: Изменение номера в LineEdit
    AID_UI->>AID_BUI: Событие OnNumberChanged
    AID_BUI->>Server: Отправка AgentIDCardNumberChangedMessage
    Server->>NanoChat: Обновление NanoChat номера
    Server->>AID_BUI: Отправка обновлённых данных (UpdateState)
    AID_BUI->>AID_UI: Вызов SetCurrentNumber для обновления отображения
    AID_UI->>Пользователь: Отображение обновлённого номера
Loading

Poem

Я кролик, весёлый и быстрый,
В коде с NanoChat сегодня праздник,
Номера меняем, сообщения летят,
Интерфейсы сияют, данные в такт!
Пусть багов будет мало, как морковок в саду –
С обновлением в системе я счастлив, как в волшебном аду! 🐇✨


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions bot added S: Untriaged Changes: Sprites Should be reviewed or fixed by people who are knowledgeable with spriting or visual design. Changes: UI Can be reviewed or fixed by people who are knowledgeable with UI design Changes: Localization Can be reviewed or fixed by people who are knowledgeable with translation size/L labels Feb 15, 2025
Copy link
Contributor

RSI Diff Bot; head commit 6ea6d61 merging into 19f835a
This PR makes changes to 1 or more RSIs. Here is a summary of all changes:

Resources/Textures/_CorvaxNext/Misc/program_icons.rsi

State Old New Status
nanochat Added

Resources/Textures/_CorvaxNext/Objects/Devices/cartridge.rsi

State Old New Status
cart-chat Added

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 19

🧹 Nitpick comments (45)
Content.Server/CartridgeLoader/Cartridges/LogProbeCartridgeComponent.cs (2)

22-27: Рекомендуется улучшить документацию свойства.

Текущая документация недостаточно подробно описывает назначение и использование свойства ScannedNanoChatData.

Предлагаю обновить документацию следующим образом:

-    /// Corvax-Next-PDAChat: The last scanned NanoChat data, if any
+    /// <summary>
+    /// Содержит данные последнего отсканированного NanoChat сообщения.
+    /// Используется для хранения информации о получателях и содержании сообщения
+    /// после сканирования NanoChat карты.
+    /// Значение null означает отсутствие отсканированных данных.
+    /// </summary>

26-27: Рекомендуется добавить ViewVariables атрибут.

Для консистентности с другими свойствами класса и удобства отладки, следует добавить атрибут ViewVariables.

Предлагаю применить следующие изменения:

     [DataField]
+    [ViewVariables]
     public NanoChatData? ScannedNanoChatData;
Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/NanoChatLogEntry.xaml.cs (1)

10-16: Добавьте проверку входных параметров и документацию.

Рекомендуется:

  1. Добавить проверку на null для строковых параметров
  2. Добавить XML-документацию для класса и конструктора
+ /// <summary>
+ /// Представляет элемент лога в NanoChat.
+ /// </summary>
 public sealed partial class NanoChatLogEntry : BoxContainer
 {
+    /// <summary>
+    /// Инициализирует новый экземпляр элемента лога.
+    /// </summary>
+    /// <param name="number">Номер сообщения</param>
+    /// <param name="time">Время отправки</param>
+    /// <param name="message">Текст сообщения</param>
+    /// <exception cref="ArgumentNullException">Если time или message равны null</exception>
     public NanoChatLogEntry(int number, string time, string message)
     {
+        ArgumentNullException.ThrowIfNull(time);
+        ArgumentNullException.ThrowIfNull(message);
+
         RobustXamlLoader.Load(this);
         NumberLabel.Text = number.ToString();
         TimeLabel.Text = time;
         MessageLabel.Text = message;
     }
Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/NanoChatLogEntry.xaml (2)

6-19: Улучшите доступность и UX компонента.

Текущая реализация может иметь проблемы с доступностью и юзабилити:

  1. При обрезании текста (ClipText="True") пользователь не видит полное содержимое
  2. Фиксированная ширина может создавать проблемы при локализации
     <BoxContainer Orientation="Horizontal">
         <Label Name="NumberLabel"
                Align="Right"
                SetWidth="26"
-               ClipText="True" />
+               ClipText="True"
+               ToolTip="{Binding Text}" />
         <Label Name="TimeLabel"
                Align="Center"
                SetWidth="100"
-               ClipText="True" />
+               ClipText="True"
+               ToolTip="{Binding Text}" />
         <Label Name="MessageLabel"
                Align="Left"
                MinWidth="390"
                HorizontalExpand="True"
-               ClipText="False" />
+               ClipText="False"
+               ToolTip="{Binding Text}" />

1-21: Рассмотрите использование стилей для унификации дизайна.

Для улучшения поддержки и консистентности интерфейса рекомендуется вынести общие свойства в стили.

 <BoxContainer xmlns="https://spacestation14.io"
               xmlns:customControls="clr-namespace:Content.Client.Administration.UI.CustomControls"
+              xmlns:styles="clr-namespace:Content.Client.Styles"
               Margin="4"
               Orientation="Vertical">
+    <BoxContainer.Resources>
+        <Style TargetType="Label">
+            <Setter Property="ClipText" Value="True" />
+            <Setter Property="ToolTip" Value="{Binding Text}" />
+        </Style>
+    </BoxContainer.Resources>
     <!-- ... остальной код ... -->
Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/NanoChatMessageBubble.xaml.cs (2)

9-17: Рекомендуется вынести цветовые константы в конфигурацию темы.

Для улучшения поддержки и возможности изменения темы оформления, рекомендуется перенести цветовые константы в отдельный конфигурационный файл темы.

Предлагаемая структура:

// ThemeColors.cs
public static class ThemeColors
{
    public static class NanoChat
    {
        public static readonly Color OwnMessage = Color.FromHex("#173717d9");
        public static readonly Color OtherMessage = Color.FromHex("#252525d9");
        public static readonly Color Border = Color.FromHex("#40404066");
        public static readonly Color Text = Color.FromHex("#dcdcdc");
        public static readonly Color Error = Color.FromHex("#cc3333");
    }
}

46-47: Удалите непрофессиональный комментарий!

Комментарий "fuuuuuck" необходимо заменить на информативное описание проблемы или решения.

Content.Server/_CorvaxNext/CartridgeLoader/Cartridges/LogProbeCartridgeSystem.NanoChat.cs (1)

16-36: Оптимизация обработки обновления получателей.

Текущая реализация создаёт новую копию словаря получателей при каждом обновлении. Для больших списков это может быть неэффективно.

Предлагаю оптимизировать код следующим образом:

-            probe.ScannedNanoChatData = new NanoChatData(
-                new Dictionary<uint, NanoChatRecipient>(card.Recipients),
-                probe.ScannedNanoChatData.Value.Messages,
-                card.Number,
-                GetNetEntity(args.CardUid));
+            var recipients = probe.ScannedNanoChatData.Value.Recipients;
+            recipients.Clear();
+            foreach (var kvp in card.Recipients)
+                recipients[kvp.Key] = kvp.Value;
+            
+            probe.ScannedNanoChatData = new NanoChatData(
+                recipients,
+                probe.ScannedNanoChatData.Value.Messages,
+                card.Number,
+                GetNetEntity(args.CardUid));
Content.Server/_CorvaxNext/NanoChat/NanoChatSystem.cs (3)

20-23: Рекомендация использовать конфигурируемые вероятности вместо хардкода
В коде жёстко зашиты проценты вероятности (10%, 90%, 50%, 25%). Для более гибкой настройки и тестирования может быть полезно вынести эти значения в конфигурационные параметры или константы.


58-68: Использование ScrambleMessages после стирания
Если стирание не произошло (90% случаев), вызывается ScrambleMessages. Логика выглядит целостно, но обратите внимание, что при некоторых сценариях может потребоваться уведомлять пользователя о смене получателей и содержимого, чтобы избежать путаницы.


73-102: Оптимизация ScrambleMessages при больших объемах данных
В циклах вложенных сообщений потенциальна высокая сложность при большом количестве получателей и сообщений. Если NanoChat в будущем будет поддерживать множество записей, рассмотрите оптимизацию или отдельный поток обработки для избежания задержек в основном потоке.

Content.Client/CartridgeLoader/Cartridges/LogProbeUiFragment.xaml.cs (4)

19-35: Метод UpdateState с различными состояниями
Реализация метода UpdateState обрабатывает два сценария (NanoChatData и AccessLogs). Код выглядит читабельным. Рекомендуется дополнительно логгировать, почему именно выбран тот или иной путь (для отладки).


37-52: Управление UI для NanoChat
Метод SetupNanoChatView корректно изменяет заголовки и располагает текст. Возможно, стоит также выводить более детальную информацию о карте или описывать пустую информацию, если CardNumber отсутствует.


61-119: Метод DisplayNanoChatData и раздельный показ входящих/исходящих сообщений
Подход с двумя отдельными циклами для входящих и исходящих сообщений упрощает чтение, однако сводит все сообщения в один список. Можно рассмотреть отображение их вперемешку по временной метке, чтобы визуально соответствовать реальному диалогу.


122-124: Метод DisplayAccessLogs
Вынос логики журнала доступа в отдельный метод повышает удобочитаемость. Текущий подход с реверсом списка даёт естественный порядок снизу вверх, что может сбивать с толку некоторых пользователей. Возможен вывод в хронологическом порядке сверху вниз.

Content.Shared/_CorvaxNext/NanoChat/SharedNanoChatSystem.cs (3)

20-32: Уточнить, какую информацию следует отображать при осмотре
Текущее поведение при отсутствии номера карты выглядит ожидаемо. Однако при необходимости в будущем можно дополнить логику — например, если потребуется отображать статус карты или дополнительную информацию. Убедитесь, что функциональность масштабируется под возможные новые требования.


220-241: Уточнить семантику частичного удаления переписки
Метод TryDeleteChat предлагает возможность удаления только чата из списка получателей, сохраняя сообщения (флаг keepMessages). Если по бизнес-логике ожидается полная очистка истории, имеет смысл явно разделить сценарии «сохранить историю» и «полностью удалить».


248-270: Упростить логику обеспечения существования получателя
В EnsureRecipientExists при отсутствии контакта метод добавляет новую запись. Желательно рассмотреть, нужно ли отдельное поведение при передаче null в recipientInfo, чтобы не смешивать ответственность создания и проверки. Это повысит читаемость и расширяемость кода.

Content.Server/_CorvaxNext/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.cs (4)

74-105: Проверить корректность фильтрации входящих сообщений
Метод OnMessage отвергает сообщения, если msg.RecipientNumber или msg.Content равны null. Возможно, стоит логировать ситуацию или уведомлять пользователя о некорректном вводе. Это поможет избежать вопросов, почему сообщение не доставлено.


214-259: Учесть возможное отсутствие валидного номера у отправителя
В HandleSendMessage метод проверяет card.Comp.Number. Если оно null, отправка сообщения невозможна. Можно рассмотреть дополнительное уведомление пользователю или логику восстановления номера, чтобы избежать «тихого» игнорирования.


278-344: Оптимизировать поиск получателей
При проверке получателей в AttemptMessageDelivery система последовательно ищет все карточки, а затем в цикле проверяет все картриджи. Если число игроков и станций вырастет, это может стать узким местом. Возможна оптимизация, например, хеширование известных номеров или кеширование картриджей по номеру.


393-423: Добавить гибкую настройку уведомлений
Метод HandleUnreadNotification отправляет уведомление, если уведомления не отключены и статус непрочитанного ещё не установлен. Если впоследствии появятся категории уведомлений или приоритеты, может понадобиться более гибкая система фильтров.

Content.Server/_CorvaxNext/CartridgeLoader/Cartridges/NanoChatCartridgeComponent.cs (1)

9-26: Рекомендуется добавить валидацию для RadioChannel!

Хотя реализация в целом корректна, рекомендуется добавить проверку значения RadioChannel при инициализации, чтобы гарантировать существование указанного канала.

Предлагаю добавить валидацию в конструкторе или методе Initialize:

private void Initialize()
{
    if (!_prototypeManager.HasIndex<RadioChannelPrototype>(RadioChannel))
    {
        Logger.Warning($"Invalid radio channel {RadioChannel} specified for {nameof(NanoChatCartridgeComponent)}");
        RadioChannel = "Common";
    }
}
Content.Shared/_CorvaxNext/CartridgeLoader/Cartridges/NanoChatUiState.cs (1)

15-29: Рассмотрите использование инициализации с помощью init-only свойств

Текущая реализация с конструктором работает корректно, но можно сделать код более лаконичным, используя init-only свойства C#.

-    public readonly Dictionary<uint, NanoChatRecipient> Recipients = new();
-    public readonly Dictionary<uint, List<NanoChatMessage>> Messages = new();
-    public readonly uint? CurrentChat;
-    public readonly uint OwnNumber;
-    public readonly int MaxRecipients;
-    public readonly bool NotificationsMuted;
+    public Dictionary<uint, NanoChatRecipient> Recipients { get; init; } = new();
+    public Dictionary<uint, List<NanoChatMessage>> Messages { get; init; } = new();
+    public uint? CurrentChat { get; init; }
+    public uint OwnNumber { get; init; }
+    public int MaxRecipients { get; init; }
+    public bool NotificationsMuted { get; init; }
Content.Shared/CartridgeLoader/Cartridges/LogProbeUiState.cs (1)

22-22: Исправьте отступ для консистентности

В строке используется табуляция вместо пробелов, что не соответствует стилю остального кода.

-		NanoChatData = nanoChatData; // Corvax-Next-PDAChat
+        NanoChatData = nanoChatData; // Corvax-Next-PDAChat
Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/NanoChatEntry.xaml.cs (1)

20-38: Отличная реализация обработки событий!

Метод SetRecipient правильно управляет жизненным циклом обработчиков событий, очищая старые обработчики перед установкой новых. Визуальная обратная связь для выбранного состояния реализована корректно.

Рассмотрите добавление проверки на null

Добавьте проверку параметра recipient для предотвращения потенциальных NullReferenceException.

 public void SetRecipient(NanoChatRecipient recipient, uint number, bool isSelected)
 {
+    if (recipient == null)
+        throw new ArgumentNullException(nameof(recipient));
+
     // Remove old handler if it exists
     if (_pressHandler != null)
         ChatButton.OnPressed -= _pressHandler;
Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/NanoChatUi.cs (1)

33-42: Добавьте валидацию входных параметров.

Метод SendNanoChatUiMessage не проверяет входные параметры на null или некорректные значения.

Предлагаемое исправление:

     private static void SendNanoChatUiMessage(NanoChatUiMessageType type,
         uint? number,
         string? content,
         string? job,
         BoundUserInterface userInterface)
     {
+        ArgumentNullException.ThrowIfNull(userInterface, nameof(userInterface));
+
         var nanoChatMessage = new NanoChatUiMessageEvent(type, number, content, job);
         var message = new CartridgeUiMessage(nanoChatMessage);
         userInterface.SendMessage(message);
     }
Resources/Locale/ru-RU/_corvaxnext/cartridge-loader/nanochat.ftl (1)

12-12: Улучшите формулировку сообщения о длине.

Текущая формулировка может быть непонятна пользователю.

Предлагаемое исправление:

-nano-chat-message-too-long = Сообщение содержит ({$current}/{$max} символов)
+nano-chat-message-too-long = Сообщение слишком длинное ({$current} из {$max} символов)
Content.Shared/_CorvaxNext/NanoChat/NanoChatCardComponent.cs (2)

45-45: Реализуйте ограничение частоты отправки сообщений.

TODO комментарий указывает на необходимость реализации ограничения частоты отправки сообщений.

Хотите, чтобы я создал issue для отслеживания этой задачи и предложил реализацию системы ограничения частоты отправки сообщений?


39-39: Вынесите максимальное количество получателей в конфигурацию.

Жестко закодированное значение MaxRecipients = 50 лучше вынести в конфигурационный файл для более гибкой настройки.

Предлагаемое исправление:

     [DataField]
-    public int MaxRecipients = 50;
+    public int MaxRecipients = IoCManager.Resolve<IConfigurationManager>()
+        .GetCVar(CCVars.NanoChatMaxRecipients);
Content.Client/CartridgeLoader/Cartridges/LogProbeUiFragment.xaml (4)

21-25: Рекомендуется добавить анимацию появления номера карты.

Для улучшения UX, рассмотрите возможность добавления плавной анимации при изменении свойства Visible.

 <Label Name="CardNumberLabel"
        StyleClasses="LabelSubText"
        HorizontalAlignment="Center"
        Margin="0 0 0 8"
-       Visible="False"/>
+       Visible="False">
+    <Label.Styles>
+        <Style Selector="Label">
+            <Style.Animations>
+                <Animation Property="Opacity" 
+                           From="0.0" To="1.0" 
+                           Duration="0.3"/>
+            </Style.Animations>
+        </Style>
+    </Label.Styles>
+</Label>

12-19: Добавьте атрибут AccessText для улучшения доступности.

Для заголовка следует добавить атрибут AccessText для улучшения доступности интерфейса.

 <Label Name="TitleLabel"
        Text="{Loc 'log-probe-header-access'}"
        StyleClasses="LabelHeading"
        HorizontalAlignment="Center"
+       AccessText="True"
        Margin="0 0 0 8"/>

21-25: Рассмотрите использование привязки данных для Visible.

Вместо жесткого задания Visible="False", лучше использовать привязку данных для динамического управления видимостью.

 <Label Name="CardNumberLabel"
        StyleClasses="LabelSubText"
        HorizontalAlignment="Center"
        Margin="0 0 0 8"
-       Visible="False"/>
+       Visible="{Binding HasCardNumber}"/>

28-32: Предложение по улучшению макета колонок.

Текущая реализация с фиксированной шириной колонок может вызвать проблемы при локализации на другие языки.

Рекомендуется использовать относительные размеры:

-                <Label Align="Right" SetWidth="26" ClipText="True" Text="{Loc 'log-probe-label-number'}"/>
-                <Label Align="Center" SetWidth="100" ClipText="True" Text="{Loc 'log-probe-label-time'}"/>
-                <Label Name="ContentLabel" Align="Left" SetWidth="390" ClipText="True" Text="{Loc 'log-probe-label-accessor'}"/>
+                <Label Align="Right" HorizontalExpand="True" MinWidth="26" ClipText="True" Text="{Loc 'log-probe-label-number'}"/>
+                <Label Align="Center" HorizontalExpand="True" MinWidth="100" ClipText="True" Text="{Loc 'log-probe-label-time'}"/>
+                <Label Name="ContentLabel" Align="Left" HorizontalExpand="True" MinWidth="200" ClipText="True" Text="{Loc 'log-probe-label-accessor'}"/>
Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/NanoChatEntry.xaml (4)

5-9: Добавьте атрибуты доступности для кнопки чата.

Для улучшения доступности интерфейса, рекомендуется добавить роль и описание для кнопки.

 <Button Name="ChatButton"
         StyleClasses="ButtonSquare"
         HorizontalExpand="True"
         MaxSize="137 64"
-        Margin="0 1">
+        Margin="0 1"
+        ToolTip.Tip="{Loc 'nano-chat-open-conversation'}"
+        AccessKeyHint="O">

17-27: Рассмотрите добавление анимации для индикатора непрочитанных сообщений.

Плавная пульсация индикатора может улучшить привлечение внимания пользователя.

 <PanelContainer Name="UnreadIndicator"
                 MinSize="8 8"
                 MaxSize="8 8"
                 VerticalAlignment="Center"
-                Margin="0 0 6 0">
+                Margin="0 0 6 0">
+    <PanelContainer.Styles>
+        <Style Selector="PanelContainer">
+            <Style.Animations>
+                <Animation Property="Opacity" 
+                           From="0.6" To="1.0" 
+                           Duration="1.0"
+                           RepeatCount="INFINITY"/>
+            </Style.Animations>
+        </Style>
+    </PanelContainer.Styles>

5-9: Добавьте ToolTip для улучшения UX.

Кнопка чата должна иметь подсказку для улучшения пользовательского опыта.

 <Button Name="ChatButton"
         StyleClasses="ButtonSquare"
         HorizontalExpand="True"
         MaxSize="137 64"
+        ToolTip="{Loc 'nano-chat-entry-tooltip'}"
         Margin="0 1">

17-27: Рассмотрите вынесение стилей в отдельный ресурс.

Стили индикатора непрочитанных сообщений лучше вынести в отдельный ресурс для переиспользования.

Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/NewChatPopup.xaml (2)

11-13: Рекомендуется добавить валидацию на стороне UI

Для улучшения UX рекомендуется добавить атрибуты валидации непосредственно в XAML:

  • MaxLength для ограничения длины ввода
  • ToolTip для отображения требований к вводу
-    <LineEdit Name="NumberInput"
-              PlaceHolder="{Loc nano-chat-number-placeholder}" />
+    <LineEdit Name="NumberInput"
+              MaxLength="4"
+              ToolTip="{Loc nano-chat-number-tooltip}"
+              PlaceHolder="{Loc nano-chat-number-placeholder}" />

Also applies to: 21-23, 31-33


40-49: Рекомендуется добавить горячие клавиши

Для улучшения UX рекомендуется добавить горячие клавиши для кнопок:

  • Enter для Create
  • Escape для Cancel
     <Button Name="CancelButton"
             Text="{Loc nano-chat-cancel}"
             StyleClasses="OpenRight"
-            MinSize="80 0" />
+            MinSize="80 0"
+            Access.Key="Escape" />
     <Button Name="CreateButton"
             Text="{Loc nano-chat-create}"
             StyleClasses="OpenLeft"
             MinSize="80 0"
-            Disabled="True" />
+            Disabled="True"
+            Access.Key="Return" />
Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/NewChatPopup.xaml.cs (1)

52-57: Добавить санитизацию для поля Job

Рекомендуется добавить очистку ввода от специальных символов и лишних пробелов для поля Job, как это сделано для других полей.

         JobInput.OnTextChanged += args =>
         {
             if (args.Text.Length > MaxInputLength)
                 JobInput.Text = args.Text[..MaxInputLength];
+            // Sanitize input
+            var newText = new string(JobInput.Text.Where(c => char.IsLetterOrDigit(c) || char.IsWhiteSpace(c)).ToArray());
+            if (newText != JobInput.Text)
+                JobInput.Text = newText;
         };
Content.Shared/Access/SharedAgentIDCardSystem.cs (1)

42-52: Улучшить документацию нового класса сообщений

Рекомендуется добавить полную документацию для нового класса AgentIDCardNumberChangedMessage.

-    // Corvax-Next-PDAChat - Add number change message
+    /// <summary>
+    /// Сообщение, отправляемое при изменении номера NanoChat в ID карте агента.
+    /// Используется для синхронизации состояния между клиентом и сервером.
+    /// </summary>
     [Serializable, NetSerializable]
     public sealed class AgentIDCardNumberChangedMessage : BoundUserInterfaceMessage
     {
+        /// <summary>
+        /// Новый номер NanoChat.
+        /// </summary>
         public uint Number { get; }
 
         public AgentIDCardNumberChangedMessage(uint number)
Content.Server/CartridgeLoader/Cartridges/LogProbeCartridgeSystem.cs (1)

55-55: Исправить отступ

Обнаружена проблема с форматированием кода - используется табуляция вместо пробелов.

-		ent.Comp.ScannedNanoChatData = null; // Corvax-Next-PDAChat - Clear any previous NanoChat data
+        ent.Comp.ScannedNanoChatData = null; // Corvax-Next-PDAChat - Clear any previous NanoChat data
Content.Shared/_CorvaxNext/CartridgeLoader/Cartridges/NanoChatUiMessageEvent.cs (1)

59-59: Удалите ненужный комментарий.

Комментарий "putting this here because i can" не несет полезной информации и должен быть удален.

-// putting this here because i can
Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/NanoChatMessageBubble.xaml (1)

19-35: Добавьте анимацию для улучшения отзывчивости интерфейса.

Рекомендуется добавить анимацию появления сообщений для улучшения пользовательского опыта.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 19f835a and 6ea6d61.

⛔ Files ignored due to path filters (5)
  • Resources/Textures/_CorvaxNext/Interface/VerbIcons/bell.svg is excluded by !**/*.svg
  • Resources/Textures/_CorvaxNext/Interface/VerbIcons/bell.svg.png is excluded by !**/*.png
  • Resources/Textures/_CorvaxNext/Interface/VerbIcons/bell_muted.png is excluded by !**/*.png
  • Resources/Textures/_CorvaxNext/Misc/program_icons.rsi/nanochat.png is excluded by !**/*.png
  • Resources/Textures/_CorvaxNext/Objects/Devices/cartridge.rsi/cart-chat.png is excluded by !**/*.png
📒 Files selected for processing (46)
  • Content.Client/Access/UI/AgentIDCardBoundUserInterface.cs (2 hunks)
  • Content.Client/Access/UI/AgentIDCardWindow.xaml (1 hunks)
  • Content.Client/Access/UI/AgentIDCardWindow.xaml.cs (2 hunks)
  • Content.Client/CartridgeLoader/Cartridges/LogProbeUi.cs (1 hunks)
  • Content.Client/CartridgeLoader/Cartridges/LogProbeUiFragment.xaml (1 hunks)
  • Content.Client/CartridgeLoader/Cartridges/LogProbeUiFragment.xaml.cs (2 hunks)
  • Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/NanoChatEntry.xaml (1 hunks)
  • Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/NanoChatEntry.xaml.cs (1 hunks)
  • Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/NanoChatLogEntry.xaml (1 hunks)
  • Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/NanoChatLogEntry.xaml.cs (1 hunks)
  • Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/NanoChatMessageBubble.xaml (1 hunks)
  • Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/NanoChatMessageBubble.xaml.cs (1 hunks)
  • Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/NanoChatUi.cs (1 hunks)
  • Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/NanoChatUiFragment.xaml (1 hunks)
  • Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/NanoChatUiFragment.xaml.cs (1 hunks)
  • Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/NewChatPopup.xaml (1 hunks)
  • Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/NewChatPopup.xaml.cs (1 hunks)
  • Content.Client/_CorvaxNext/NanoChat/NanoChatSystem.cs (1 hunks)
  • Content.Server/Access/Systems/AgentIDCardSystem.cs (5 hunks)
  • Content.Server/CartridgeLoader/Cartridges/LogProbeCartridgeComponent.cs (2 hunks)
  • Content.Server/CartridgeLoader/Cartridges/LogProbeCartridgeSystem.cs (5 hunks)
  • Content.Server/_CorvaxNext/CartridgeLoader/Cartridges/LogProbeCartridgeSystem.NanoChat.cs (1 hunks)
  • Content.Server/_CorvaxNext/CartridgeLoader/Cartridges/NanoChatCartridgeComponent.cs (1 hunks)
  • Content.Server/_CorvaxNext/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.cs (1 hunks)
  • Content.Server/_CorvaxNext/NanoChat/NanoChatSystem.cs (1 hunks)
  • Content.Shared/Access/SharedAgentIDCardSystem.cs (1 hunks)
  • Content.Shared/CartridgeLoader/Cartridges/LogProbeUiState.cs (2 hunks)
  • Content.Shared/_CorvaxNext/CartridgeLoader/Cartridges/NanoChatUiMessageEvent.cs (1 hunks)
  • Content.Shared/_CorvaxNext/CartridgeLoader/Cartridges/NanoChatUiState.cs (1 hunks)
  • Content.Shared/_CorvaxNext/NanoChat/NanoChatCardComponent.cs (1 hunks)
  • Content.Shared/_CorvaxNext/NanoChat/SharedNanoChatSystem.cs (1 hunks)
  • Resources/Locale/en-US/_corvaxnext/access/components/agent-id-card-component.ftl (1 hunks)
  • Resources/Locale/en-US/_corvaxnext/cartridge-loader/nanochat.ftl (1 hunks)
  • Resources/Locale/en-US/_corvaxnext/nanochat/components/nanochat-card-component.ftl (1 hunks)
  • Resources/Locale/ru-RU/_corvaxnext/access/components/agent-id-card-component.ftl (1 hunks)
  • Resources/Locale/ru-RU/_corvaxnext/cartridge-loader/nanochat.ftl (1 hunks)
  • Resources/Locale/ru-RU/_corvaxnext/nanochat/components/nanochat-card-component.ftl (1 hunks)
  • Resources/Locale/ru-RU/backmen/disease/disease.ftl (1 hunks)
  • Resources/Locale/ru-RU/backmen/disease/swab.ftl (1 hunks)
  • Resources/Prototypes/Entities/Objects/Devices/pda.yml (6 hunks)
  • Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml (2 hunks)
  • Resources/Prototypes/_CorvaxNext/Entities/Objects/Devices/cartridges.yml (1 hunks)
  • Resources/Prototypes/_CorvaxNext/name_identifier_groups.yml (1 hunks)
  • Resources/Textures/_CorvaxNext/Interface/VerbIcons/ATTRIBUTION.txt (1 hunks)
  • Resources/Textures/_CorvaxNext/Misc/program_icons.rsi/meta.json (1 hunks)
  • Resources/Textures/_CorvaxNext/Objects/Devices/cartridge.rsi/meta.json (1 hunks)
✅ Files skipped from review due to trivial changes (7)
  • Resources/Locale/en-US/_corvaxnext/access/components/agent-id-card-component.ftl
  • Resources/Textures/_CorvaxNext/Interface/VerbIcons/ATTRIBUTION.txt
  • Resources/Locale/ru-RU/backmen/disease/disease.ftl
  • Resources/Textures/_CorvaxNext/Objects/Devices/cartridge.rsi/meta.json
  • Resources/Textures/_CorvaxNext/Misc/program_icons.rsi/meta.json
  • Resources/Locale/ru-RU/_corvaxnext/access/components/agent-id-card-component.ftl
  • Resources/Locale/ru-RU/backmen/disease/swab.ftl
⏰ Context from checks skipped due to timeout of 300000ms (3)
  • GitHub Check: Test Packaging
  • GitHub Check: build (ubuntu-latest)
  • GitHub Check: build (ubuntu-latest)
🔇 Additional comments (53)
Content.Server/CartridgeLoader/Cartridges/LogProbeCartridgeComponent.cs (1)

2-2: Добавление директивы using для NanoChat функционала.

Директива необходима для использования типа NanoChatData из пространства имен Corvax.

Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/NanoChatMessageBubble.xaml.cs (1)

1-8: Корректные импорты и пространство имён!

Структура импортов и пространства имён соответствует архитектуре проекта.

Content.Server/_CorvaxNext/CartridgeLoader/Cartridges/LogProbeCartridgeSystem.NanoChat.cs (1)

8-14: Структура класса и инициализация реализованы корректно!

Хорошее разделение логики с использованием partial класса и правильная подписка на события.

Content.Server/_CorvaxNext/NanoChat/NanoChatSystem.cs (2)

33-46: Проверить корректность удаления сообщений при одновременной микроволновке
Метод OnMicrowaved мгновенно очищает или изменяет коллекцию Messages, однако при возможном одновременном доступе других систем могут возникать гонки. Убедитесь, что любое параллельное использование исключено или корректно синхронизировано.


104-118: Реализация Fisher-Yates для перестановки
Алгоритм перемешивания символов выглядит корректным и завершённым. При этом будьте осторожны с многострочными сообщениями и любыми спецсимволами — в некоторых случаях можно добавить проверку на юникод-суррогаты или эмодзи, хотя в большинстве случаев это не критично.

Content.Server/Access/Systems/AgentIDCardSystem.cs (5)

12-13: Подключение пространства имён NanoChat
Импорт пакета Content.Shared._CorvaxNext.NanoChat выглядит уместно. Убедитесь, что не появляется конфликтов с другими системами, использующими похожие пространства имён.


22-22: Добавление SharedNanoChatSystem в зависимости
Добавление _nanoChat обеспечивает взаимодействие с NanoChat-картами. Убедитесь в корректной инициализации, чтобы исключить ситуации, когда _nanoChat вызывается до своего Initialize().


33-34: Подписка на AgentIDCardNumberChangedMessage
Подключение нового события для изменения номера карты NanoChat. Общая структура соответствует остальным сообщениям системы.


36-44: Обработка OnNumberChanged
Метод корректно ищет компонент NanoChatCardComponent и затем устанавливает новый номер через _nanoChat. Рекомендуется проверить, не будет ли нарушено логическое состояние, если карта уже имеет другой номер, и как это обрабатывается с точки зрения пользовательского интерфейса.


112-120: Обновлённая логика AfterUIOpen
Передача текущего номера NanoChat в состояние интерфейса упрощает отображение данных. Убедитесь, что логика обновления номера (через OnNumberChanged) и интерфейса остаётся синхронизированной для пользователя.

Content.Shared/_CorvaxNext/NanoChat/SharedNanoChatSystem.cs (2)

39-57: Убедиться в корректной обработке отсутствующего компонента
Методы GetNumber и SetNumber используют Resolve для поиска NanoChatCardComponent. Это удобный подход, однако в случаях, когда card может быть неверно сопоставлен или отсутствовать, стоит проверить, не возникнут ли случайные ошибки в вызовах из других систем.


118-132: Учесть возможную параллельную модификацию словаря
При добавлении нового сообщения одновременно несколькими источниками может возникнуть гонка, если выполнение не строго однопоточное. Если в контексте игры все системные вызовы происходят последовательно, риск минимален. Но при расширении или тестировании многопоточности стоит рассмотреть блокировку словаря при записи, чтобы предотвратить потенциальные коллизии.

Content.Server/_CorvaxNext/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.cs (1)

132-152: Обратить внимание на выбор названия для контакта
При создании нового чата (HandleNewChat) имя (msg.Content) используется для обозначения получателя. Убедитесь, что бизнес-логика предусматривает хранение имени в этом поле и что его изменение действительно сигнализирует о названиях получателей (и не конфликтует с текстом сообщения).

Resources/Locale/en-US/_corvaxnext/nanochat/components/nanochat-card-component.ftl (1)

1-5: Локализация реализована корректно!

Строки локализации хорошо структурированы и содержат всю необходимую информацию для пользователя. Переменные правильно используются в шаблонах.

Resources/Locale/ru-RU/_corvaxnext/nanochat/components/nanochat-card-component.ftl (1)

1-5: Перевод выполнен качественно!

Русские строки локализации точно передают смысл оригинала, при этом звучат естественно. Форматирование и использование переменных соответствует стандартам.

Content.Server/_CorvaxNext/CartridgeLoader/Cartridges/NanoChatCartridgeComponent.cs (1)

6-8: Компонент правильно зарегистрирован!

Атрибуты регистрации и доступа корректно настроены для компонента.

Content.Client/CartridgeLoader/Cartridges/LogProbeUi.cs (1)

26-26: Изменение в передаче состояния реализовано корректно!

Передача полного объекта состояния вместо отдельного свойства позволяет более гибко обрабатывать данные в UI-фрагменте. Изменение хорошо задокументировано комментарием.

Content.Client/Access/UI/AgentIDCardWindow.xaml (1)

9-12: Корректное добавление поля для номера NanoChat!

Поле для ввода номера NanoChat хорошо интегрировано в существующий интерфейс. Плейсхолдер "#0000" наглядно показывает ожидаемый формат.

Content.Shared/_CorvaxNext/CartridgeLoader/Cartridges/NanoChatUiState.cs (1)

5-13: Хорошая структура класса состояния UI!

Класс правильно помечен как сериализуемый и использует неизменяемые поля для хранения данных состояния. Структура данных логично организована для управления чатами и получателями.

Content.Shared/CartridgeLoader/Cartridges/LogProbeUiState.cs (1)

14-17: Хорошее документирование нового функционала!

Добавление поддержки NanoChat хорошо задокументировано с помощью XML-комментариев.

Resources/Locale/en-US/_corvaxnext/cartridge-loader/nanochat.ftl (1)

1-37: Локализация выполнена корректно!

Файл содержит все необходимые строки для интерфейса NanoChat с правильным форматированием и поддержкой динамического контента.

Content.Client/CartridgeLoader/Cartridges/LogProbeUiFragment.xaml (6)

12-19: Хорошая структура заголовка!

Добавление заголовка с использованием LabelHeading и центрирование улучшает визуальную иерархию интерфейса.


28-32: Проверьте доступность интерфейса.

Убедитесь, что текст в колонках имеет достаточный контраст и размер для комфортного чтения. Также рекомендуется добавить всплывающие подсказки для обрезанного текста.

 <BoxContainer Orientation="Horizontal">
     <Label Align="Right" SetWidth="26" ClipText="True" Text="{Loc 'log-probe-label-number'}"
+           ToolTip.Tip="{Binding Text, RelativeSource={RelativeSource Self}}"/>
     <Label Align="Center" SetWidth="100" ClipText="True" Text="{Loc 'log-probe-label-time'}"
+           ToolTip.Tip="{Binding Text, RelativeSource={RelativeSource Self}}"/>
     <Label Name="ContentLabel" Align="Left" SetWidth="390" ClipText="True" Text="{Loc 'log-probe-label-accessor'}"
+           ToolTip.Tip="{Binding Text, RelativeSource={RelativeSource Self}}"/>
 </BoxContainer>

28-32: LGTM! Хорошая структура заголовков колонок.

Структура заголовков колонок хорошо организована с использованием фиксированной ширины и выравнивания.


4-5: Правильная реорганизация контейнеров!

Вертикальная ориентация корневого контейнера и вложенного BoxContainer обеспечивает логичное расположение элементов интерфейса сверху вниз.

Also applies to: 12-12


14-18: Хорошее добавление заголовка!

Заголовок правильно локализован и отцентрирован. Использование StyleClasses="LabelHeading" обеспечивает единый стиль с другими заголовками.


21-25:

❓ Verification inconclusive

Проверьте логику видимости CardNumberLabel.

Label изначально скрыт (Visible="False"). Убедитесь, что в code-behind правильно реализована логика отображения номера карты.


🏁 Script executed:

#!/bin/bash
# Поиск логики управления видимостью CardNumberLabel
ast-grep --pattern 'CardNumberLabel.Visible = $_'

Length of output: 51


Проверьте логику управления видимостью CardNumberLabel

В XAML элемент CardNumberLabel изначально скрыт (Visible="False"). Однако поиск через ast-grep --pattern 'CardNumberLabel.Visible = $_' не обнаружил прямых изменений свойства в code-behind, что вызывает вопросы:

  • Если управление видимостью осуществляется программно, убедитесь, что соответствующий код действительно изменяет состояние элемента (например, присваивая CardNumberLabel.Visible = true в нужных случаях).
  • Если применяется привязка или иной косвенный метод (например, изменение через data-binding или команды), убедитесь, что этот механизм корректно работает и обновляет UI согласно ожидаемой логике.

Пожалуйста, проведите дополнительную проверку работы логики изменения видимости либо вручную, либо с помощью дополнительного поиска в коде.

Content.Server/CartridgeLoader/Cartridges/LogProbeCartridgeSystem.cs (1)

22-22:

❌ Incorrect review comment

Отсутствует реализация метода InitializeNanoChat

В файле вызывается метод InitializeNanoChat(), но его реализация отсутствует. Необходимо добавить реализацию или предоставить информацию о том, где она находится.


🏁 Script executed:

#!/bin/bash
# Search for InitializeNanoChat implementation
rg -l "InitializeNanoChat"

Length of output: 200


Реализация метода обнаружена
При поиске реализации метода InitializeNanoChat были найдены следующие файлы:

  • Content.Server/_CorvaxNext/CartridgeLoader/Cartridges/LogProbeCartridgeSystem.NanoChat.cs
  • NanoChat.patch

Таким образом, реализация метода присутствует в кодовой базе, а не отсутствует. Рекомендуется обновить комментарий, указав, что метод реализован в отдельном файле (например, добавить комментарий с указанием файла реализации) или пояснить архитектурное решение.

Likely an incorrect or invalid review comment.

Content.Client/Access/UI/AgentIDCardWindow.xaml.cs (3)

24-24: Константа и событие корректно определены!

Константа MaxNumberLength и событие OnNumberChanged правильно определены для обработки номера NanoChat.

Also applies to: 29-29


42-63: Обработка ввода номера реализована корректно!

Код включает:

  • Валидацию длины номера
  • Фильтрацию на ввод только цифр
  • Обработку граничных случаев

73-76: Метод форматирования номера реализован правильно!

Метод SetCurrentNumber корректно обрабатывает:

  • Форматирование номера с ведущими нулями
  • Случай с null значением
Content.Shared/_CorvaxNext/CartridgeLoader/Cartridges/NanoChatUiMessageEvent.cs (6)

6-46: Класс события сообщения реализован корректно!

  • Правильно настроена сериализация
  • Все свойства хорошо документированы
  • Конструктор имеет опциональные параметры

49-57: Перечисление типов сообщений определено корректно!

Enum NanoChatUiMessageType охватывает все необходимые действия для работы чата.


61-97: Структура получателя реализована корректно!

  • Правильно настроена сериализация
  • Все свойства хорошо документированы
  • Конструктор имеет все необходимые параметры

100-137: Структура сообщения реализована корректно!

  • Правильно настроена сериализация
  • Все свойства хорошо документированы
  • Реализовано отслеживание статуса доставки

144-154: Структура данных чата реализована корректно!

  • Использован современный синтаксис C# record
  • Правильно настроена сериализация
  • Все свойства имеют правильные типы данных

160-160: События обновления получателя и получения сообщения реализованы корректно!

  • Использован атрибут [ByRefEvent]
  • Использован современный синтаксис C# record
  • События хорошо документированы

Also applies to: 166-166

Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/NanoChatUiFragment.xaml (3)

16-75: Заголовок интерфейса реализован корректно!

  • Включены все необходимые элементы управления
  • Правильно структурирована разметка
  • Корректно определены иконки и подсказки

83-103: Список чатов реализован корректно!

  • Реализована прокрутка
  • Обработано состояние пустого списка
  • Правильно определены ограничения макета

108-164: Область сообщений реализована корректно!

  • Включены все необходимые компоненты
  • Правильно реализована область ввода
  • Корректно обрабатываются счетчик символов и кнопка отправки
Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/NanoChatUiFragment.xaml.cs (4)

17-80: Инициализация и настройка событий реализованы корректно!

  • Правильно определены константы и зависимости
  • Хорошо организованы обработчики событий
  • Корректно реализована валидация ввода

82-114: Обработка сообщений реализована корректно!

  • Реализовано предсказание сообщений
  • Обработаны ошибочные ситуации
  • Правильно обновляется интерфейс

116-144: Выбор и удаление чатов реализованы корректно!

  • Правильно реализована логика выбора
  • Предотвращен повторный выбор
  • Корректно обрабатывается удаление

145-253: Методы обновления интерфейса реализованы корректно!

  • Обновления охватывают все аспекты
  • Правильно управляется состояние
  • Корректно обрабатывается синхронизация интерфейса
Resources/Prototypes/_CorvaxNext/name_identifier_groups.yml (1)

1-5: Проверка определения группы идентификаторов NanoChat.
Добавлен новый блок с типом nameIdentifierGroup для идентификаторов NanoChat с параметром maxValue: 9999. Всё оформлено корректно и соответствует ожидаемой конфигурации.

Resources/Prototypes/_CorvaxNext/Entities/Objects/Devices/cartridges.yml (1)

1-21: Добавление сущности NanoChatCartridge.
Новая сущность NanoChatCartridge создана с необходимыми компонентами:
• Компонент Sprite для визуального отображения (используется спрайт cartridge.rsi с состоянием cart-chat).
• Компонент UIFragment для привязки UI-фрагмента, отвечающего за обработку интерфейса NanoChat.
• Собственный компонент NanoChatCartridge для специфичного функционала системы NanoChat.
• Компонент Cartridge, задающий программное имя (nano-chat-program-name) и иконку (спрайт из program_icons.rsi с состоянием nanochat).
• Компонент ActiveRadio для определения каналов связи (канал Common).
Структура выглядит логично и единообразно – изменений не требуется.

Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml (1)

846-848: Интеграция компонента NanoChatCard в ID-карты.
Новый компонент NanoChatCard добавлен в состав идентификационной карточки с параметром notificationsMuted: true, что отключает уведомления для NanoChat режима. Убедитесь, что данное изменение согласовано с логикой обновлённого UI и обработкой данных в бэкенде.

Resources/Prototypes/Entities/Objects/Devices/pda.yml (6)

144-146: Добавление NanoChatCartridge в BaseSecurityPDA.
В сущности BaseSecurityPDA в список предустановленных картриджей добавлен NanoChatCartridge с комментарием # Corvax-Next-PDAChat. Это изменение корректно расширяет функционал для обеспечения NanoChat в системе безопасности.


856-858: Добавление NanoChatCartridge в HoSPDA.
В блоке HoSPDA добавлена строка с NanoChatCartridge в список предустановленных картриджей. Рекомендуется проверить корректность интеграции с остальными компонентами PDA, чтобы функционал NanoChat работал без конфликтов.


927-929: Внедрение NanoChatCartridge в CentcomPDA.
В сущности CentcomPDA дополнительно к другим картриджам добавлен NanoChatCartridge, что позволяет использовать NanoChat на этом устройстве. Проверка на соответствие общей архитектуре устройства выполнена успешно.


1090-1102: Добавление NanoChatCartridge в ERTLeaderPDA.
Новый предустановленный картридж NanoChatCartridge добавлен в конфигурацию ERTLeaderPDA. Необходимо убедиться, что пользовательский интерфейс для этого устройства корректно обрабатывает функции NanoChat.


1260-1271: Интеграция NanoChatCartridge в DetectivePDA.
В DetectivePDA внесена модификация с добавлением NanoChatCartridge в список картриджей. Данное изменение расширяет функциональность обмена сообщениями, и структура блока выглядит корректно – проверьте отсутствие конфликтов с другими компонентами.


1297-1299: Добавление NanoChatCartridge в BrigmedicPDA.
В сущности BrigmedicPDA добавлен NanoChatCartridge для активации NanoChat-функционала. Изменение интегрируется в общий список предустановленных картриджей и соответствует целям расширения коммуникационных возможностей устройств.

Comment on lines +18 to +21
public NanoChatMessageBubble()
{
RobustXamlLoader.Load(this);
}
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

Добавьте обработку ошибок при загрузке XAML!

Отсутствие обработки ошибок при загрузке XAML может привести к сбоям во время выполнения. Рекомендуется добавить try-catch блок.

Предлагаемое исправление:

 public NanoChatMessageBubble()
 {
-    RobustXamlLoader.Load(this);
+    try
+    {
+        RobustXamlLoader.Load(this);
+    }
+    catch (Exception ex)
+    {
+        Logger.Error($"Ошибка при загрузке XAML для NanoChatMessageBubble: {ex}");
+        throw;
+    }
 }
📝 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
public NanoChatMessageBubble()
{
RobustXamlLoader.Load(this);
}
public NanoChatMessageBubble()
{
try
{
RobustXamlLoader.Load(this);
}
catch (Exception ex)
{
Logger.Error($"Ошибка при загрузке XAML для NanoChatMessageBubble: {ex}");
throw;
}
}

Comment on lines +23 to +61
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);
}
}
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

Добавьте проверки на null и упростите манипуляции с UI!

В методе SetMessage есть несколько моментов, требующих улучшения:

  1. Отсутствуют проверки на null для UI элементов
  2. Сложная логика манипуляции с дочерними элементами может быть упрощена

Предлагаемое исправление:

 public void SetMessage(NanoChatMessage message, bool isOwnMessage)
 {
+    if (MessagePanel?.PanelOverride is not StyleBoxFlat style)
+        return;
+    
+    if (MessageText == null || MessageContainer == null || MessageBox == null)
+        return;
 
-    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)
+    if (DeliveryFailedLabel != null)
+    {
+        DeliveryFailedLabel.Visible = isOwnMessage && message.DeliveryFailed;
+        if (DeliveryFailedLabel.Visible)
         DeliveryFailedLabel.Modulate = ErrorColor;
+    }
 
     MessageContainer.RemoveAllChildren();
-    MessageBox.Parent?.RemoveChild(MessageBox);
+    
+    var elements = isOwnMessage
+        ? new Control[] { FlexSpace, MessageBox, RightSpacer }
+        : new Control[] { LeftSpacer, MessageBox, FlexSpace };
 
-    if (isOwnMessage)
-    {
-        MessageContainer.AddChild(FlexSpace);
-        MessageContainer.AddChild(MessageBox);
-        MessageContainer.AddChild(RightSpacer);
-    }
-    else
-    {
-        MessageContainer.AddChild(LeftSpacer);
-        MessageContainer.AddChild(MessageBox);
-        MessageContainer.AddChild(FlexSpace);
-    }
+    foreach (var element in elements)
+    {
+        if (element != null)
+            MessageContainer.AddChild(element);
+    }
 }
📝 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
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);
}
}
public void SetMessage(NanoChatMessage message, bool isOwnMessage)
{
if (MessagePanel?.PanelOverride is not StyleBoxFlat style)
return;
if (MessageText == null || MessageContainer == null || MessageBox == null)
return;
// Configure message appearance
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)
if (DeliveryFailedLabel != null)
{
DeliveryFailedLabel.Visible = isOwnMessage && message.DeliveryFailed;
if (DeliveryFailedLabel.Visible)
DeliveryFailedLabel.Modulate = ErrorColor;
}
MessageContainer.RemoveAllChildren();
var elements = isOwnMessage
? new Control[] { FlexSpace, MessageBox, RightSpacer }
: new Control[] { LeftSpacer, MessageBox, FlexSpace };
foreach (var element in elements)
{
if (element != null)
MessageContainer.AddChild(element);
}
}

Comment on lines +60 to +81
private void ScanNanoChatCard(Entity<LogProbeCartridgeComponent> ent,
CartridgeAfterInteractEvent args,
EntityUid target,
NanoChatCardComponent card)
{
_audioSystem.PlayEntity(ent.Comp.SoundScan,
args.InteractEvent.User,
target,
AudioHelpers.WithVariation(0.25f, _random));
_popupSystem.PopupCursor(Loc.GetString("log-probe-scan-nanochat", ("card", target)), args.InteractEvent.User);

ent.Comp.PulledAccessLogs.Clear();

ent.Comp.ScannedNanoChatData = new NanoChatData(
new Dictionary<uint, NanoChatRecipient>(card.Recipients),
new Dictionary<uint, List<NanoChatMessage>>(card.Messages),
card.Number,
GetNetEntity(target)
);

UpdateUiState(ent, args.Loader);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Проверка безопасности сканирования карты.

Метод корректно очищает старые данные и обновляет состояние, но стоит проверить наличие ограничений на размер сообщений и списка получателей.

Давайте проверим, есть ли в системе ограничения на размер данных:


🏁 Script executed:

#!/bin/bash
# Поиск ограничений на размер данных в компонентах NanoChat

# Проверяем ограничения в компоненте NanoChatCardComponent
rg -A 5 "NanoChatCardComponent" 

# Ищем валидацию размера сообщений
rg -A 5 "Messages.*Add|Recipients.*Add" 

Length of output: 63876


ВНИМАНИЕ: проверка безопасности сканирования NanoChat карты

Метод ScanNanoChatCard корректно сбрасывает предыдущие данные, обновляет состояние интерфейса и обеспечивает обратную связь (звуковые сигналы и всплывающие уведомления). Однако наблюдается отсутствие явных ограничений на количество сообщений и получателей, что может привести к потенциальным проблемам с производительностью или утечке памяти при чрезмерно больших объёмах данных.

Рекомендуемые действия:

  • Проверьте, предусматривается ли в компонентах (например, в NanoChatCardComponent и системе NanoChat) валидация или ограничение на максимальное количество элементов в словарях Recipients и Messages.
  • При отсутствии таких проверок, рассмотрите возможность введения ограничений (например, максимальное число сообщений или получателей) и соответствующей обработки ошибок или логирования при превышении этих лимитов.

Comment on lines +38 to +58
private void OnMessageReceived(ref NanoChatMessageReceivedEvent args)
{
var query = EntityQueryEnumerator<LogProbeCartridgeComponent, CartridgeComponent>();
while (query.MoveNext(out var uid, out var probe, out var cartridge))
{
if (probe.ScannedNanoChatData == null || GetEntity(probe.ScannedNanoChatData.Value.Card) != args.CardUid)
continue;

if (!TryComp<NanoChatCardComponent>(args.CardUid, out var card))
continue;

probe.ScannedNanoChatData = new NanoChatData(
probe.ScannedNanoChatData.Value.Recipients,
new Dictionary<uint, List<NanoChatMessage>>(card.Messages),
card.Number,
GetNetEntity(args.CardUid));

if (cartridge.LoaderUid != null)
UpdateUiState((uid, probe), cartridge.LoaderUid.Value);
}
}
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

Устранение дублирования кода в обработчиках событий.

Обработчики OnRecipientUpdated и OnMessageReceived содержат много повторяющейся логики запросов и валидации.

Предлагаю вынести общую логику в отдельный метод:

+    private bool TryGetProbeAndCard(EntityUid cardUid, 
+        out (EntityUid Uid, LogProbeCartridgeComponent Probe, CartridgeComponent Cartridge) result,
+        out NanoChatCardComponent card)
+    {
+        card = default!;
+        result = default;
+        
+        var query = EntityQueryEnumerator<LogProbeCartridgeComponent, CartridgeComponent>();
+        while (query.MoveNext(out var uid, out var probe, out var cartridge))
+        {
+            if (probe.ScannedNanoChatData == null || 
+                GetEntity(probe.ScannedNanoChatData.Value.Card) != cardUid)
+                continue;
+
+            if (!TryComp<NanoChatCardComponent>(cardUid, out card))
+                return false;
+
+            result = (uid, probe, cartridge);
+            return true;
+        }
+        return false;
+    }

Затем использовать его в обработчиках:

-        var query = EntityQueryEnumerator<LogProbeCartridgeComponent, CartridgeComponent>();
-        while (query.MoveNext(out var uid, out var probe, out var cartridge))
-        {
-            if (probe.ScannedNanoChatData == null || GetEntity(probe.ScannedNanoChatData.Value.Card) != args.CardUid)
-                continue;
-
-            if (!TryComp<NanoChatCardComponent>(args.CardUid, out var card))
-                continue;
+        if (!TryGetProbeAndCard(args.CardUid, out var result, out var card))
+            return;
+            
+        var (uid, probe, cartridge) = result;
📝 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
private void OnMessageReceived(ref NanoChatMessageReceivedEvent args)
{
var query = EntityQueryEnumerator<LogProbeCartridgeComponent, CartridgeComponent>();
while (query.MoveNext(out var uid, out var probe, out var cartridge))
{
if (probe.ScannedNanoChatData == null || GetEntity(probe.ScannedNanoChatData.Value.Card) != args.CardUid)
continue;
if (!TryComp<NanoChatCardComponent>(args.CardUid, out var card))
continue;
probe.ScannedNanoChatData = new NanoChatData(
probe.ScannedNanoChatData.Value.Recipients,
new Dictionary<uint, List<NanoChatMessage>>(card.Messages),
card.Number,
GetNetEntity(args.CardUid));
if (cartridge.LoaderUid != null)
UpdateUiState((uid, probe), cartridge.LoaderUid.Value);
}
}
private bool TryGetProbeAndCard(EntityUid cardUid,
out (EntityUid Uid, LogProbeCartridgeComponent Probe, CartridgeComponent Cartridge) result,
out NanoChatCardComponent card)
{
card = default!;
result = default;
var query = EntityQueryEnumerator<LogProbeCartridgeComponent, CartridgeComponent>();
while (query.MoveNext(out var uid, out var probe, out var cartridge))
{
if (probe.ScannedNanoChatData == null ||
GetEntity(probe.ScannedNanoChatData.Value.Card) != cardUid)
continue;
if (!TryComp<NanoChatCardComponent>(cardUid, out card))
return false;
result = (uid, probe, cartridge);
return true;
}
return false;
}
private void OnMessageReceived(ref NanoChatMessageReceivedEvent args)
{
if (!TryGetProbeAndCard(args.CardUid, out var result, out var card))
return;
var (uid, probe, cartridge) = result;
probe.ScannedNanoChatData = new NanoChatData(
probe.ScannedNanoChatData.Value.Recipients,
new Dictionary<uint, List<NanoChatMessage>>(card.Messages),
card.Number,
GetNetEntity(args.CardUid));
if (cartridge.LoaderUid != null)
UpdateUiState((uid, probe), cartridge.LoaderUid.Value);
}

Comment on lines +58 to +85
// Corvax-Next-PDAChat-Start - Copy NanoChat data if available
if (TryComp<NanoChatCardComponent>(args.Target, out var targetNanoChat) &&
TryComp<NanoChatCardComponent>(uid, out var agentNanoChat))
{
// First clear existing data
_nanoChat.Clear((uid, agentNanoChat));

// Copy the number
if (_nanoChat.GetNumber((args.Target.Value, targetNanoChat)) is { } number)
_nanoChat.SetNumber((uid, agentNanoChat), number);

// Copy all recipients and their messages
foreach (var (recipientNumber, recipient) in _nanoChat.GetRecipients((args.Target.Value, targetNanoChat)))
{
_nanoChat.SetRecipient((uid, agentNanoChat), recipientNumber, recipient);

if (_nanoChat.GetMessagesForRecipient((args.Target.Value, targetNanoChat), recipientNumber) is not
{ } messages)
continue;

foreach (var message in messages)
{
_nanoChat.AddMessage((uid, agentNanoChat), recipientNumber, message);
}
}
}
// Corvax-Next-PDAChat-End

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

Копирование NanoChat-данных
Реализована логика копирования чатов с одной карты на другую при взаимодействии. Потенциально необходимо убедиться, что при копировании большего объёма диалогов всё корректно обрабатывается и не возникает переполнений или задержек. Можно добавить логирование результата копирования.

Comment on lines +11 to +12
private const int MaxInputLength = 16;
private const int MaxNumberLength = 4; // i hardcoded it to be 4 so suffer
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

Константы требуют рефакторинга

Рекомендуется:

  1. Перенести константы в конфигурационный файл
  2. Убрать комментарий о "страдании"
  3. Добавить документацию о причине выбора значений

Comment on lines +28 to +43
NumberInput.OnTextChanged += _ => ValidateInputs();
NameInput.OnTextChanged += _ => ValidateInputs();

// Input validation
NumberInput.OnTextChanged += args =>
{
if (args.Text.Length > MaxNumberLength)
NumberInput.Text = args.Text[..MaxNumberLength];

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

ValidateInputs();
};
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

Исправить дублирование обработчиков событий

У NumberInput.OnTextChanged определено два обработчика, что может привести к непредсказуемому поведению.

-        NumberInput.OnTextChanged += _ => ValidateInputs();
         NumberInput.OnTextChanged += args =>
         {
             if (args.Text.Length > MaxNumberLength)
                 NumberInput.Text = args.Text[..MaxNumberLength];
 
             // Filter to digits only
             var newText = string.Concat(NumberInput.Text.Where(char.IsDigit));
             if (newText != NumberInput.Text)
                 NumberInput.Text = newText;
 
             ValidateInputs();
         };
📝 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
NumberInput.OnTextChanged += _ => ValidateInputs();
NameInput.OnTextChanged += _ => ValidateInputs();
// Input validation
NumberInput.OnTextChanged += args =>
{
if (args.Text.Length > MaxNumberLength)
NumberInput.Text = args.Text[..MaxNumberLength];
// Filter to digits only
var newText = string.Concat(NumberInput.Text.Where(char.IsDigit));
if (newText != NumberInput.Text)
NumberInput.Text = newText;
ValidateInputs();
};
NameInput.OnTextChanged += _ => ValidateInputs();
// Input validation
NumberInput.OnTextChanged += args =>
{
if (args.Text.Length > MaxNumberLength)
NumberInput.Text = args.Text[..MaxNumberLength];
// Filter to digits only
var newText = string.Concat(NumberInput.Text.Where(char.IsDigit));
if (newText != NumberInput.Text)
NumberInput.Text = newText;
ValidateInputs();
};

Comment on lines +31 to 32
public uint? CurrentNumber { get; } // Corvax-Next-PDAChat

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

Добавить XML документацию

Необходимо добавить XML документацию для нового свойства CurrentNumber с описанием его назначения и возможных значений.

+        /// <summary>
+        /// Текущий номер NanoChat, связанный с ID картой.
+        /// Null означает, что номер не установлен.
+        /// </summary>
         public uint? CurrentNumber { get; } // Corvax-Next-PDAChat
📝 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
public uint? CurrentNumber { get; } // Corvax-Next-PDAChat
/// <summary>
/// Текущий номер NanoChat, связанный с ID картой.
/// Null означает, что номер не установлен.
/// </summary>
public uint? CurrentNumber { get; } // Corvax-Next-PDAChat

Comment on lines +39 to +45
if (TryComp<NanoChatCardComponent>(target, out var nanoChatCard))
{
ScanNanoChatCard(ent, args, target, nanoChatCard);
args.InteractEvent.Handled = true;
return;
}
// Corvax-Next-PDAChat-End
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

Добавить обработку ошибок

Рекомендуется добавить обработку ошибок при сканировании NanoChat карты и информативные сообщения для пользователя в случае неудачи.

         if (TryComp<NanoChatCardComponent>(target, out var nanoChatCard))
         {
+            try
+            {
                 ScanNanoChatCard(ent, args, target, nanoChatCard);
+            }
+            catch (Exception ex)
+            {
+                _popupSystem.PopupCursor(Loc.GetString("log-probe-scan-failed"), args.InteractEvent.User);
+                Log.Error($"Failed to scan NanoChat card: {ex}");
+            }
             args.InteractEvent.Handled = true;
             return;
         }
📝 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
if (TryComp<NanoChatCardComponent>(target, out var nanoChatCard))
{
ScanNanoChatCard(ent, args, target, nanoChatCard);
args.InteractEvent.Handled = true;
return;
}
// Corvax-Next-PDAChat-End
if (TryComp<NanoChatCardComponent>(target, out var nanoChatCard))
{
try
{
ScanNanoChatCard(ent, args, target, nanoChatCard);
}
catch (Exception ex)
{
_popupSystem.PopupCursor(Loc.GetString("log-probe-scan-failed"), args.InteractEvent.User);
Log.Error($"Failed to scan NanoChat card: {ex}");
}
args.InteractEvent.Handled = true;
return;
}
// Corvax-Next-PDAChat-End

Comment on lines +34 to +44
<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" />
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

Добавьте обработку переполнения текста.

Для меток имени и должности следует добавить обработку случаев переполнения текста.

 <RichTextLabel Name="NameLabel"
                StyleClasses="LabelHeading"
                HorizontalExpand="True"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
+               ClipText="True"
                Margin="0 -2 0 0" />
📝 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
<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" />
<RichTextLabel Name="NameLabel"
StyleClasses="LabelHeading"
HorizontalExpand="True"
HorizontalAlignment="Center"
VerticalAlignment="Center"
ClipText="True"
Margin="0 -2 0 0" />
<Label Name="JobLabel"
StyleClasses="LabelSubText"
HorizontalExpand="True"
ClipText="False"
HorizontalAlignment="Center" />

Copy link
Contributor

@Roudenn Roudenn left a comment

Choose a reason for hiding this comment

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

Он поклялся своей мамой что этот ПР работает

@Roudenn Roudenn merged commit 7e89e45 into Rxup:master Feb 16, 2025
19 checks passed
Rxup added a commit that referenced this pull request Feb 16, 2025
@Rxup Rxup mentioned this pull request Feb 16, 2025
Rxup added a commit that referenced this pull request Feb 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Changes: Localization Can be reviewed or fixed by people who are knowledgeable with translation Changes: Sprites Should be reviewed or fixed by people who are knowledgeable with spriting or visual design. Changes: UI Can be reviewed or fixed by people who are knowledgeable with UI design S: Untriaged size/L
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants