Show server and channel group icons in the tree
Download the icons a server advertises for its groups over the file transfer channel, cache them under the config directory, and draw them as a badge strip on each client's row, right-aligned against the tree's visible edge like the TeamSpeak client does. Groups without a custom icon fall back to the bundled default set. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,12 +2,15 @@ package com.ts3client.ui;
|
||||
|
||||
import com.ts3client.net.ChannelNode;
|
||||
import com.ts3client.net.ClientEntry;
|
||||
import com.ts3client.net.Group;
|
||||
import com.ts3client.net.IconRepository;
|
||||
import com.ts3client.net.ServerModel;
|
||||
import com.ts3client.text.BBCode;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.JEditorPane;
|
||||
import javax.swing.JScrollPane;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -67,15 +70,27 @@ public final class InfoPanel extends JScrollPane {
|
||||
setHtml(sb.toString());
|
||||
}
|
||||
|
||||
public void showClient(ClientEntry cl, ServerModel model) {
|
||||
public void showClient(ClientEntry cl, ServerModel model, IconRepository icons) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(heading(esc(cl.nickname) + (cl.self ? " <span style='color:#8a8a8a'>(you)</span>" : "")));
|
||||
|
||||
List<String> serverGroups = model.serverGroupNames(cl.serverGroupIds);
|
||||
row(sb, "Server groups", serverGroups.isEmpty() ? "—" : esc(String.join(", ", serverGroups)));
|
||||
List<Group> serverGroups = model.serverGroupsOf(cl.serverGroupIds);
|
||||
if (serverGroups.isEmpty()) {
|
||||
List<String> names = model.serverGroupNames(cl.serverGroupIds);
|
||||
row(sb, "Server groups", names.isEmpty() ? "—" : esc(String.join(", ", names)));
|
||||
} else {
|
||||
StringBuilder groups = new StringBuilder();
|
||||
for (Group g : serverGroups) {
|
||||
if (groups.length() > 0) groups.append(", ");
|
||||
groups.append(iconTag(g, icons)).append(esc(g.name));
|
||||
}
|
||||
row(sb, "Server groups", groups.toString());
|
||||
}
|
||||
|
||||
String channelGroup = model.channelGroupName(cl.channelGroupId);
|
||||
row(sb, "Channel group", channelGroup != null ? esc(channelGroup) : "#" + cl.channelGroupId);
|
||||
Group channelGroup = model.channelGroup(cl.channelGroupId);
|
||||
row(sb, "Channel group", channelGroup != null
|
||||
? iconTag(channelGroup, icons) + esc(channelGroup.name)
|
||||
: "#" + cl.channelGroupId);
|
||||
|
||||
if (cl.talkPower != 0) row(sb, "Talk power", Integer.toString(cl.talkPower));
|
||||
if (!cl.platform.isEmpty()) row(sb, "Platform", esc(cl.platform));
|
||||
@@ -97,6 +112,18 @@ public final class InfoPanel extends JScrollPane {
|
||||
pane.setCaretPosition(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* An inline {@code <img>} for a group's icon, or nothing while the icon is missing
|
||||
* or still downloading. Swing's HTML renderer only loads images by URL, so the icon
|
||||
* is served from the repository's on-disk cache.
|
||||
*/
|
||||
private static String iconTag(Group group, IconRepository icons) {
|
||||
if (group.iconId == 0) return "";
|
||||
File file = icons.file(group.iconId);
|
||||
if (file == null) return "";
|
||||
return "<img src='" + file.toURI() + "' width='14' height='14'> ";
|
||||
}
|
||||
|
||||
private static String heading(String text) {
|
||||
return "<div style='font-weight:bold;font-size:13px;margin-bottom:4px'>" + text + "</div>";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user