From 8e3e9401d2d3808a8fcd1edf591c358b0e564c9f Mon Sep 17 00:00:00 2001 From: ericek111 Date: Thu, 20 Aug 2026 06:57:38 +0000 Subject: [PATCH] Name the server and channel chat tabs after where we are Both carry an icon now, as the private chats do. Co-Authored-By: Claude Opus 5 --- .../main/java/com/ts3client/ui/ChatPanel.java | 34 +++++++++++++++---- .../src/main/java/com/ts3client/ui/Icons.java | 12 +++++++ .../ui/ServerTabConnectionEvents.java | 16 +++++++++ 3 files changed, 56 insertions(+), 6 deletions(-) diff --git a/ts3-client/swing/src/main/java/com/ts3client/ui/ChatPanel.java b/ts3-client/swing/src/main/java/com/ts3client/ui/ChatPanel.java index b9f96f1..58741da 100644 --- a/ts3-client/swing/src/main/java/com/ts3client/ui/ChatPanel.java +++ b/ts3-client/swing/src/main/java/com/ts3client/ui/ChatPanel.java @@ -58,8 +58,11 @@ public final class ChatPanel extends JPanel { private final JTextField input = new JTextField(); private final SimpleDateFormat time = new SimpleDateFormat("HH:mm:ss"); - private final Tab serverTab = new Tab(Target.SERVER, 0, "Server"); - private final Tab channelTab = new Tab(Target.CHANNEL, 0, "Channel"); + private static final String NO_SERVER = "Server"; + private static final String NO_CHANNEL = "Channel"; + + private final Tab serverTab = new Tab(Target.SERVER, 0, NO_SERVER, Icons.server()); + private final Tab channelTab = new Tab(Target.CHANNEL, 0, NO_CHANNEL, Icons.channelChat()); /** Private chats keyed by the peer's client id. */ private final Map privateTabs = new LinkedHashMap<>(); /** Static-content tabs (e.g. a moved-out description), keyed by caller-chosen id. */ @@ -116,6 +119,16 @@ public final class ChatPanel extends JPanel { }); } + /** Names the server tab after the server we are on; blank falls back to "Server". */ + public void setServerName(String name) { + edt(() -> serverTab.setTitle(name == null || name.isBlank() ? NO_SERVER : name)); + } + + /** Names the channel tab after the channel we are in; blank falls back to "Channel". */ + public void setChannelName(String name) { + edt(() -> channelTab.setTitle(name == null || name.isBlank() ? NO_CHANNEL : name)); + } + public void setInputEnabled(boolean enabled) { input.setEnabled(enabled); } @@ -218,7 +231,7 @@ public final class ChatPanel extends JPanel { private Tab privateTab(int clientId, String nickname) { Tab tab = privateTabs.get(clientId); if (tab == null) { - tab = new Tab(Target.PRIVATE, clientId, nickname); + tab = new Tab(Target.PRIVATE, clientId, nickname, Icons.privateChat()); privateTabs.put(clientId, tab); addTab(tab, true); } @@ -285,7 +298,7 @@ public final class ChatPanel extends JPanel { final Target target; final int clientId; - final String title; + private String title; final JEditorPane log = HtmlStyles.pane("font-family:sans-serif; font-size:11px; margin:4px 6px;"); final JScrollPane scroll; /** Set for a static-content tab (e.g. a moved-out description); null for a conversation. */ @@ -294,8 +307,8 @@ public final class ChatPanel extends JPanel { private final Icon icon; private JLabel titleLabel; - Tab(Target target, int clientId, String title) { - this(target, clientId, title, null, null, null); + Tab(Target target, int clientId, String title, Icon icon) { + this(target, clientId, title, icon, null, null); } /** A static-content tab: no send target, closing it runs {@code onClose}. */ @@ -369,6 +382,15 @@ public final class ChatPanel extends JPanel { return p; } + /** Renames the tab in place — the server and channel tabs follow where we are. */ + void setTitle(String title) { + if (title.equals(this.title)) return; + this.title = title; + int index = tabs.indexOfComponent(scroll); + if (index >= 0) tabs.setTitleAt(index, title); + if (titleLabel != null) titleLabel.setText(title); + } + void setUnread(boolean unread) { if (titleLabel == null) return; titleLabel.setFont(unread ? Theme.uiBold() : Theme.uiFont()); diff --git a/ts3-client/swing/src/main/java/com/ts3client/ui/Icons.java b/ts3-client/swing/src/main/java/com/ts3client/ui/Icons.java index af4141a..3bd324b 100644 --- a/ts3-client/swing/src/main/java/com/ts3client/ui/Icons.java +++ b/ts3-client/swing/src/main/java/com/ts3client/ui/Icons.java @@ -114,6 +114,18 @@ public final class Icons { return subscribed ? new String[]{base + "_SUBSCRIBED", base} : new String[]{base}; } + /** The chat tab for the current channel. */ + public static ImageIcon channelChat() { + ImageIcon icon = of("CHANNEL_CHAT"); + return icon != null ? icon : channel(true); + } + + /** The chat tab of a private conversation. */ + public static ImageIcon privateChat() { + ImageIcon icon = ofAny("PLAYER_CHAT", "NEW_CHAT"); + return icon != null ? icon : clientIdle(); + } + // ---- client status icons ---- public static ImageIcon clientIdle() { diff --git a/ts3-client/swing/src/main/java/com/ts3client/ui/ServerTabConnectionEvents.java b/ts3-client/swing/src/main/java/com/ts3client/ui/ServerTabConnectionEvents.java index dd2528e..30c9414 100644 --- a/ts3-client/swing/src/main/java/com/ts3client/ui/ServerTabConnectionEvents.java +++ b/ts3-client/swing/src/main/java/com/ts3client/ui/ServerTabConnectionEvents.java @@ -1,5 +1,7 @@ package com.ts3client.ui; +import com.ts3client.net.ChannelNode; +import com.ts3client.net.ClientEntry; import com.ts3client.net.ConnectionListener; import com.ts3client.net.TeamspeakConnection; @@ -50,6 +52,14 @@ final class ServerTabConnectionEvents implements ConnectionListener { this.treeActions = treeActions; } + /** Name of the channel we are in, or null while that is not known yet. */ + private String currentChannelName() { + ClientEntry self = conn.getModel().getClient(conn.getSelfClientId()); + if (self == null) return null; + ChannelNode ch = conn.getModel().getChannel(self.channelId); + return ch == null ? null : ch.name; + } + @Override public void onStatus(String text) { SwingUtilities.invokeLater(() -> { @@ -80,6 +90,8 @@ final class ServerTabConnectionEvents implements ConnectionListener { chatPanel.setInputEnabled(false); chatPanel.closePrivateChats(); chatPanel.closeNoteTabs(); + chatPanel.setServerName(null); + chatPanel.setChannelName(null); chatPanel.appendSystem("Disconnected" + (reason == null || reason.isEmpty() ? "." : ": " + reason)); host.tabDisconnected(tab); }); @@ -96,6 +108,10 @@ final class ServerTabConnectionEvents implements ConnectionListener { listener.setTitle(name); host.tabUpdated(tab); } + if (conn.isConnected()) { + chatPanel.setServerName(name); + chatPanel.setChannelName(currentChannelName()); + } }); }