Add the Create Channel dialog

The official client creates and edits channels with one dialog, so
ChannelEditDialog becomes ChannelDialog with two entry points. Creating
starts from caller-chosen defaults instead of a channelinfo and sends a
channelcreate carrying only what deviates from a plain new channel —
TeamSpeak checks a create permission per property that is present.

The server row now has a context menu with "Create Channel" and "Create
Spacer" (pre-filled with the lowest free [spacerN], since channel names
must be unique), and a channel's menu offers "Create Channel" and
"Create Sub-Channel", both starting out temporary.

Verified against the test server: a temporary channel is created, and a
permanent one a guest may not create reports the server's refusal.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-19 15:31:07 +00:00
parent d8a56566d4
commit f2885d33ad
13 changed files with 279 additions and 29 deletions

View File

@@ -1,6 +1,7 @@
package com.ts3client.ui;
import com.ts3client.net.ChannelNode;
import com.ts3client.net.ChannelSettings;
import com.ts3client.net.ClientEntry;
import com.ts3client.net.Group;
import com.ts3client.net.ServerModel;
@@ -47,6 +48,20 @@ public final class ServerTreePanel extends JScrollPane {
/** Opens the channel editor for a channel. */
void editChannel(ChannelNode channel);
/**
* Opens the channel creator.
*
* @param parent the channel the new one goes below, or {@code null} for a top-level one
* @param type the channel type to start with
*/
void createChannel(ChannelNode parent, ChannelSettings.Type type);
/** Opens the channel creator pre-filled as a spacer, which is always top-level. */
void createSpacer();
/** Whether the server is there to act on at all. */
boolean isConnected();
/** Open the file repository browser for a channel. */
void browseFiles(ChannelNode channel);
@@ -196,6 +211,9 @@ public final class ServerTreePanel extends JScrollPane {
showClientMenu((ClientEntry) obj, e);
} else if (obj instanceof ChannelNode) {
showChannelMenu((ChannelNode) obj, e);
} else if (path.getPathCount() == 1 && actions.isConnected()) {
// The root row is the server itself, whose user object is just its name.
ServerMenu.build(actions).show(tree, e.getX(), e.getY());
}
}