Я портирую систему второго ахелпа для менторов для СС14. Это очередная попытка заручиться твоей помощью. Вот UI новый:
<Control
    xmlns="https://spacestation14.io"
    xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls">
    <PanelContainer StyleClasses="BackgroundDark">
        <SplitContainer Orientation="Vertical" ResizeMode="NotResizable">
            <SplitContainer Orientation="Horizontal" VerticalExpand="True">
                <cc:PlayerListControl Access="Public" Name="ChannelSelector" HorizontalExpand="True" SizeFlagsStretchRatio="2" />
                <BoxContainer Orientation="Vertical" HorizontalExpand="True" SizeFlagsStretchRatio="2">
                    <BoxContainer Access="Public" Name="BwoinkArea" VerticalExpand="True" />
                </BoxContainer>
            </SplitContainer>
            <BoxContainer Orientation="Horizontal" SetHeight="30" >
                <CheckBox Name="AdminOnly" Access="Public" Text="{Loc 'admin-ahelp-admin-only'}" ToolTip="{Loc 'admin-ahelp-admin-only-tooltip'}" />
                <Control HorizontalExpand="True" MinWidth="5" />
                <CheckBox Name="PlaySound" Access="Public" Text="{Loc 'admin-bwoink-play-sound'}" Pressed="True" />
                <Control HorizontalExpand="True" MinWidth="5" />
                <Button Visible="True" Name="PopOut" Access="Public" Text="{Loc 'admin-logs-pop-out'}" StyleClasses="OpenBoth" HorizontalAlignment="Left" />
                <Control HorizontalExpand="True" />
                <Button Visible="False" Name="Notes" Text="{Loc 'admin-player-actions-notes'}" StyleClasses="OpenBoth" />
                <Button Visible="False" Name="Follow" Text="{Loc 'admin-player-actions-follow'}" StyleClasses="OpenLeft" />
            </BoxContainer>
        </SplitContainer>
    </PanelContainer>
</Control>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Content.Client.Administration.Managers;
using Content.Client.Administration.UI;
using Content.Client.Administration.UI.CustomControls;
using Content.Client.UserInterface.Systems.Bwoink;
using Content.Shared.Administration;
using Content.Shared.CCVar;
using Robust.Client.AutoGenerated;
using Robust.Client.Console;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Configuration;
using Robust.Shared.Network;
using Robust.Shared.Utility;

namespace Content.Client._RMC14.Mentor
{
    [GenerateTypedNameReferences]
    public sealed partial class MentorBwoinkControl : Control
    {
        [Dependency] private readonly IClientAdminManager _adminManager = default!;
        [Dependency] private readonly IClientConsoleHost _console = default!;
        [Dependency] private readonly IUserInterfaceManager _ui = default!;
        [Dependency] private readonly IConfigurationManager _cfg = default!;

        public AdminAHelpUIHandler? AHelpHelper = null;

        private PlayerInfo? _currentPlayer;
        private readonly Dictionary<Button, ConfirmationData> _confirmations = new();

        public MentorBwoinkControl()
        {
            RobustXamlLoader.Load(this);
            IoCManager.InjectDependencies(this);

            var newPlayerThreshold = 0;
            _cfg.OnValueChanged(CCVars.NewPlayerThreshold, (val) => { newPlayerThreshold = val; }, true);

            var uiController = _ui.GetUIController<AHelpUIController>();
            if (uiController.UIHelper is not AdminAHelpUIHandler helper)
                return;

            AHelpHelper = helper;

            _adminManager.AdminStatusUpdated += UpdateButtons;
            UpdateButtons();

            ChannelSelector.OnSelectionChanged += sel =>
            {
                _currentPlayer = sel;
                SwitchToChannel(sel?.SessionId);
                ChannelSelector.PlayerListContainer.DirtyList();
            };

            ChannelSelector.OverrideText += (info, text) =>
            {
                var sb = new StringBuilder();

                if (info.Connected)
                    sb.Append(info.ActiveThisRound ? '⚫' : '◐');
                else
                    sb.Append(info.ActiveThisRound ? '⭘' : '·');

                sb.Append(' ');
                if (AHelpHelper.TryGetChannel(info.SessionId, out var panel) && panel.Unread > 0)
                {
                    if (panel.Unread < 11)
                        sb.Append(new Rune('➀' + (panel.Unread - 1)));
                    else
                        sb.Append(new Rune(0x2639)); // ☹
                    sb.Append(' ');
                }

                if (info.Antag && info.ActiveThisRound)
                    sb.Append(new Rune(0x1F5E1)); // 🗡

                if (IsNewPlayer(info, newPlayerThreshold))
                    sb.Append(new Rune(0x23F2)); // ⏲

                sb.AppendFormat("\"{0}\"", text);

                return sb.ToString();
            };

            ChannelSelector.Comparison = (a, b) =>
            {
                var ach = AHelpHelper.EnsurePanel(a.SessionId);
                var bch = AHelpHelper.EnsurePanel(b.SessionId);

                if (a.IsPinned != b.IsPinned)
                    return a.IsPinned ? -1 : 1;

                var aUnread = ach.Unread > 0;
                var bUnread = bch.Unread > 0;
                if (aUnread != bUnread)
                    return aUnread ? -1 : 1;

                var aRecent = a.ActiveThisRound && ach.LastMessage != DateTime.MinValue;
                var bRecent = b.ActiveThisRound && bch.LastMessage != DateTime.MinValue;
                if (aRecent != bRecent)
                    return aRecent ? -1 : 1;

                if (a.Connected != b.Connected)
                    return a.Connected ? -1 : 1;

                if (a.Connected && b.Connected)
                {
                    var aNewPlayer = IsNewPlayer(a, newPlayerThreshold);
                    var bNewPlayer = IsNewPlayer(b, newPlayerThreshold);

                    if (a.ActiveThisRound != b.ActiveThisRound)
                        return a.ActiveThisRound ? -1 : 1;

                    if (aNewPlayer != bNewPlayer)
                        return aNewPlayer ? -1 : 1;

                    if (a.Antag != b.Antag)
                        return a.Antag ? -1 : 1;
                }

                if (!a.Connected && !b.Connected)
                {
                    if (a.ActiveThisRound != b.ActiveThisRound)
                        return a.ActiveThisRound ? -1 : 1;
                }

                return bch.LastMessage.CompareTo(ach.LastMessage);
            };

            PlaySound.OnToggled += args =>
            {
                // Можно реализовать логику включения/выключения звука
            };

            PopOut.OnPressed += _ =>
            {
                var uiController = _ui.GetUIController<AHelpUIController>();
                uiController?.PopOut();
            };
        }

        private static bool IsNewPlayer(PlayerInfo info, int newPlayerThreshold)
        {
            if (newPlayerThreshold <= 0 || (info.OverallPlaytime is null && !info.Connected))
                return false;

            return (info.OverallPlaytime is null || info.OverallPlaytime < TimeSpan.FromMinutes(newPlayerThreshold));
        }

        public void SwitchToChannel(NetUserId? ch)
        {
            UpdateButtons();

            AHelpHelper?.HideAllPanels();
            if (ch != null)
            {
                var panel = AHelpHelper?.EnsurePanel(ch.Value);
                if (panel != null)
                    panel.Visible = true;
            }
        }

        public void PopulateList()
        {
            var pinnedPlayers = new Dictionary<NetUserId, PlayerInfo>();
            foreach (var p in ChannelSelector.PlayerInfo)
            {
                if (p.IsPinned)
                    pinnedPlayers[p.SessionId] = p;
            }

            ChannelSelector.PopulateList();

            foreach (var player in ChannelSelector.PlayerInfo)
            {
                if (pinnedPlayers.TryGetValue(player.SessionId, out var pinnedPlayer))
                    player.IsPinned = pinnedPlayer.IsPinned;
            }

            UpdateButtons();
        }

        public void UpdateButtons()
        {
            var disabled = _currentPlayer == null;

            AdminOnly.Visible = false;
            AdminOnly.Disabled = true;

            Notes.Visible = false;
            Notes.Disabled = true;

            Follow.Visible = false;
            Follow.Disabled = true;

            PlaySound.Disabled = disabled;
            PopOut.Disabled = disabled;
        }

        public void SelectChannel(NetUserId userId)
        {
            if (!ChannelSelector.PlayerInfo.TryFirstOrDefault(i => i.SessionId == userId, out var info))
                return;

            var data = new PlayerListData(info);
            if (!ChannelSelector.PlayerListContainer.Data.Contains(data))
                ChannelSelector.StopFiltering();

            ChannelSelector.PopulateList();
            ChannelSelector.PlayerListContainer.Select(data);
        }
    }
}

А вот тот, на котором он основан:
<Control
    xmlns="https://spacestation14.io"
    xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls">
    <PanelContainer StyleClasses="BackgroundDark">
        <SplitContainer Orientation="Vertical" ResizeMode="NotResizable">
            <SplitContainer Orientation="Horizontal" VerticalExpand="True">
                <cc:PlayerListControl Access="Public" Name="ChannelSelector" HorizontalExpand="True" SizeFlagsStretchRatio="2" />
                <BoxContainer Orientation="Vertical" HorizontalExpand="True" SizeFlagsStretchRatio="2">
                    <BoxContainer Access="Public" Name="BwoinkArea" VerticalExpand="True" />
                </BoxContainer>
            </SplitContainer>
            <BoxContainer Orientation="Horizontal" SetHeight="30" >
                <CheckBox Name="AdminOnly" Access="Public" Text="{Loc 'admin-ahelp-admin-only'}" ToolTip="{Loc 'admin-ahelp-admin-only-tooltip'}" />
                <Control HorizontalExpand="True" MinWidth="5" />
                <CheckBox Name="PlaySound" Access="Public" Text="{Loc 'admin-bwoink-play-sound'}" Pressed="True" />
                <Control HorizontalExpand="True" MinWidth="5" />
                <Button Visible="True" Name="PopOut" Access="Public" Text="{Loc 'admin-logs-pop-out'}" StyleClasses="OpenBoth" HorizontalAlignment="Left" />
                <Control HorizontalExpand="True" />
                <Button Visible="False" Name="Bans" Text="{Loc 'admin-player-actions-bans'}" StyleClasses="OpenRight" />
                <Button Visible="False" Name="Notes" Text="{Loc 'admin-player-actions-notes'}" StyleClasses="OpenBoth" />
                <Button Visible="False" Name="Kick" Text="{Loc 'admin-player-actions-kick'}" StyleClasses="OpenBoth" />
                <Button Visible="False" Name="Ban" Text="{Loc 'admin-player-actions-ban'}" StyleClasses="OpenBoth" />
                <Button Visible="False" Name="Respawn" Text="{Loc 'admin-player-actions-respawn'}" StyleClasses="OpenBoth" />
                <Button Visible="False" Name="Follow" Text="{Loc 'admin-player-actions-follow'}" StyleClasses="OpenLeft" />
            </BoxContainer>
        </SplitContainer>
    </PanelContainer>
</Control>

using System.Linq;
using System.Text;
using Content.Client.Administration.Managers;
using Content.Client.Administration.UI.CustomControls;
using Content.Client.UserInterface.Systems.Bwoink;
using Content.Shared.Administration;
using Content.Shared.CCVar;
using Robust.Client.AutoGenerated;
using Robust.Client.Console;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Network;
using Robust.Shared.Configuration;
using Robust.Shared.Utility;

namespace Content.Client.Administration.UI.Bwoink
{
    /// <summary>
    /// This window connects to a BwoinkSystem channel. BwoinkSystem manages the rest.
    /// </summary>
    [GenerateTypedNameReferences]
    public sealed partial class BwoinkControl : Control
    {
        [Dependency] private readonly IClientAdminManager _adminManager = default!;
        [Dependency] private readonly IClientConsoleHost _console = default!;
        [Dependency] private readonly IUserInterfaceManager _ui = default!;
        [Dependency] private readonly IConfigurationManager _cfg = default!;
        public AdminAHelpUIHandler AHelpHelper = default!;

        private PlayerInfo? _currentPlayer;
        private readonly Dictionary<Button, ConfirmationData> _confirmations = new();

        public BwoinkControl()
        {
            RobustXamlLoader.Load(this);
            IoCManager.InjectDependencies(this);

            var newPlayerThreshold = 0;
            _cfg.OnValueChanged(CCVars.NewPlayerThreshold, (val) => { newPlayerThreshold = val; }, true);

            var uiController = _ui.GetUIController<AHelpUIController>();
            if (uiController.UIHelper is not AdminAHelpUIHandler helper)
                return;

            AHelpHelper = helper;

            _adminManager.AdminStatusUpdated += UpdateButtons;
            UpdateButtons();

            AdminOnly.OnToggled += args => PlaySound.Disabled = args.Pressed;

            ChannelSelector.OnSelectionChanged += sel =>
            {
                _currentPlayer = sel;
                SwitchToChannel(sel?.SessionId);
                ChannelSelector.PlayerListContainer.DirtyList();
            };

            ChannelSelector.OverrideText += (info, text) =>
            {
                var sb = new StringBuilder();

                if (info.Connected)
                    sb.Append(info.ActiveThisRound ? '⚫' : '◐');
                else
                    sb.Append(info.ActiveThisRound ? '⭘' : '·');

                sb.Append(' ');
                if (AHelpHelper.TryGetChannel(info.SessionId, out var panel) && panel.Unread > 0)
                {
                    if (panel.Unread < 11)
                        sb.Append(new Rune('➀' + (panel.Unread-1)));
                    else
                        sb.Append(new Rune(0x2639)); // ☹
                    sb.Append(' ');
                }

                // Mark antagonists with symbol
                if (info.Antag && info.ActiveThisRound)
                    sb.Append(new Rune(0x1F5E1)); // 🗡

                // Mark new players with symbol
                if (IsNewPlayer(info))
                    sb.Append(new Rune(0x23F2)); // ⏲

                sb.AppendFormat("\"{0}\"", text);

                return sb.ToString();
            };

            // <summary>
            // Returns true if the player's overall playtime is under the set threshold
            // </summary>
            bool IsNewPlayer(PlayerInfo info)
            {
                // Don't show every disconnected player as new, don't show 0-minute players as new if threshold is
                if (newPlayerThreshold <= 0 || info.OverallPlaytime is null && !info.Connected)
                    return false;

                return (info.OverallPlaytime is null
                        || info.OverallPlaytime < TimeSpan.FromMinutes(newPlayerThreshold));
            }

            ChannelSelector.Comparison = (a, b) =>
            {
                var ach = AHelpHelper.EnsurePanel(a.SessionId);
                var bch = AHelpHelper.EnsurePanel(b.SessionId);

                // Pinned players first
                if (a.IsPinned != b.IsPinned)
                    return a.IsPinned ? -1 : 1;

                // Then, any chat with unread messages.
                var aUnread = ach.Unread > 0;
                var bUnread = bch.Unread > 0;
                if (aUnread != bUnread)
                    return aUnread ? -1 : 1;

                // Then, any chat with recent messages from the current round
                var aRecent = a.ActiveThisRound && ach.LastMessage != DateTime.MinValue;
                var bRecent = b.ActiveThisRound && bch.LastMessage != DateTime.MinValue;
                if (aRecent != bRecent)
                    return aRecent ? -1 : 1;

                // Sort by connection status. Disconnected players will be last.
                if (a.Connected != b.Connected)
                    return a.Connected ? -1 : 1;

                // Sort connected players by whether they have joined the round, then by New Player status, then by Antag status
                if (a.Connected && b.Connected)
                {
                    var aNewPlayer = IsNewPlayer(a);
                    var bNewPlayer = IsNewPlayer(b);

                    //  Players who have joined the round will be listed before players in the lobby
                    if (a.ActiveThisRound != b.ActiveThisRound)
                        return a.ActiveThisRound ? -1 : 1;

                    //  Within both the joined group and lobby group, new players will be grouped and listed first
                    if (aNewPlayer != bNewPlayer)
                        return aNewPlayer ? -1 : 1;

                    //  Within all four previous groups, antagonists will be listed first.
                    if (a.Antag != b.Antag)
                        return a.Antag ? -1 : 1;
                }

                // Sort disconnected players by participation in the round
                if (!a.Connected && !b.Connected)
                {
                    if (a.ActiveThisRound != b.ActiveThisRound)
                        return a.ActiveThisRound ? -1 : 1;
                }

                // Finally, sort by the most recent message.
                return bch.LastMessage.CompareTo(ach.LastMessage);
            };


            Bans.OnPressed += _ =>
            {
                if (_currentPlayer is not null)
                    _console.ExecuteCommand($"banlist \"{_currentPlayer.SessionId}\"");
            };

            Notes.OnPressed += _ =>
            {
                if (_currentPlayer is not null)
                    _console.ExecuteCommand($"adminnotes \"{_currentPlayer.SessionId}\"");
            };

            Ban.OnPressed += _ =>
            {
                if (_currentPlayer is not null)
                    _console.ExecuteCommand($"banpanel \"{_currentPlayer.SessionId}\"");
            };

            Kick.OnPressed += _ =>
            {
                if (!AdminUIHelpers.TryConfirm(Kick, _confirmations))
                {
                    return;
                }

                // TODO: Reason field
                if (_currentPlayer is not null)
                    _console.ExecuteCommand($"kick \"{_currentPlayer.Username}\"");
            };

            Follow.OnPressed += _ =>
            {
                if (_currentPlayer is not null)
                    _console.ExecuteCommand($"follow \"{_currentPlayer.NetEntity}\"");
            };

            Respawn.OnPressed += _ =>
            {
                if (!AdminUIHelpers.TryConfirm(Respawn, _confirmations))
                {
                    return;
                }

                if (_currentPlayer is not null)
                    _console.ExecuteCommand($"respawn \"{_currentPlayer.Username}\"");
            };

            PopOut.OnPressed += _ =>
            {
                uiController.PopOut();
            };
        }

        public void OnBwoink(NetUserId channel)
        {
            ChannelSelector.PopulateList();
        }


        public void SelectChannel(NetUserId channel)
        {
            if (!ChannelSelector.PlayerInfo.TryFirstOrDefault(
                i => i.SessionId == channel, out var info))
                return;

            // clear filter if we're trying to select a channel for a player that isn't currently filtered
            // i.e. through the message verb.
            var data = new PlayerListData(info);
            if (!ChannelSelector.PlayerListContainer.Data.Contains(data))
            {
                ChannelSelector.StopFiltering();
            }

            ChannelSelector.PopulateList();
            ChannelSelector.PlayerListContainer.Select(data);
        }

        public void UpdateButtons()
        {
            var disabled = _currentPlayer == null;

            Bans.Visible = _adminManager.HasFlag(AdminFlags.Ban);
            Bans.Disabled = !Bans.Visible || disabled;

            Notes.Visible = _adminManager.HasFlag(AdminFlags.ViewNotes);
            Notes.Disabled = !Notes.Visible || disabled;

            Ban.Visible = _adminManager.HasFlag(AdminFlags.Ban);
            Ban.Disabled = !Ban.Visible || disabled;

            Kick.Visible = _adminManager.CanCommand("kick");
            Kick.Disabled = !Kick.Visible || disabled;

            Respawn.Visible = _adminManager.CanCommand("respawn");
            Respawn.Disabled = !Respawn.Visible || disabled;

            Follow.Visible = _adminManager.CanCommand("follow");
            Follow.Disabled = !Follow.Visible || disabled;
        }

        private string FormatTabTitle(ItemList.Item li, PlayerInfo? pl = default)
        {
            pl ??= (PlayerInfo) li.Metadata!;
            var sb = new StringBuilder();
            sb.Append(pl.Connected ? '●' : '○');
            sb.Append(' ');
            if (AHelpHelper.TryGetChannel(pl.SessionId, out var panel) && panel.Unread > 0)
            {
                if (panel.Unread < 11)
                    sb.Append(new Rune('➀' + (panel.Unread-1)));
                else
                    sb.Append(new Rune(0x2639)); // ☹
                sb.Append(' ');
            }

            if (pl.Antag)
                sb.Append(new Rune(0x1F5E1)); // 🗡

            if (pl.OverallPlaytime <= TimeSpan.FromMinutes(_cfg.GetCVar(CCVars.NewPlayerThreshold)))
                sb.Append(new Rune(0x23F2)); // ⏲

            sb.AppendFormat("\"{0}\"", pl.CharacterName);

            if (pl.IdentityName != pl.CharacterName && pl.IdentityName != string.Empty)
                sb.Append(' ').AppendFormat("[{0}]", pl.IdentityName);

            sb.Append(' ').Append(pl.Username);

            return sb.ToString();
        }

        private void SwitchToChannel(NetUserId? ch)
        {
            UpdateButtons();

            AHelpHelper.HideAllPanels();
            if (ch != null)
            {
                var panel = AHelpHelper.EnsurePanel(ch.Value);
                panel.Visible = true;
            }
        }

        public void PopulateList()
        {
            // Maintain existing pin statuses
            var pinnedPlayers = ChannelSelector.PlayerInfo.Where(p => p.IsPinned).ToDictionary(p => p.SessionId);

            ChannelSelector.PopulateList();

            // Restore pin statuses
            foreach (var player in ChannelSelector.PlayerInfo)
            {
                if (pinnedPlayers.TryGetValue(player.SessionId, out var pinnedPlayer))
                {
                    player.IsPinned = pinnedPlayer.IsPinned;
                }
            }

            UpdateButtons();
        }
    }
}

Убраны лишние кнопки. Но необходимые, что присутствуют в xaml - отсутствуют на деле, как и полоса ввода текста. Поможешь?