Add identity management

Manage several TeamSpeak identities like the official client instead of
using one auto-generated identity file.

- IdentityStore/IdentityEntry keep each identity as a TeamSpeak-format INI
  in ~/.ts3jclient/identities, so files interchange with the TS3 client;
  supports create, import, export, rename, remove and a cancellable
  security-level search. A legacy identity.ini is migrated in on first load.
- Settings hold the default identity; bookmarks may pin their own, falling
  back to the default when unset.
- TeamspeakConnection now connects with the identity it is handed.
- Swing: Tools -> Identities manager, plus an identity drop-down in the
  connect and bookmark forms.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-13 07:42:08 +00:00
parent f912cab07b
commit 17ad6cde1c
12 changed files with 880 additions and 38 deletions

View File

@@ -0,0 +1,48 @@
package com.ts3client.ui;
import com.ts3client.config.IdentityEntry;
import com.ts3client.config.IdentityStore;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JComboBox;
import javax.swing.JList;
import java.awt.Component;
/**
* Drop-down for picking the identity to connect with. Optionally offers a
* "use the default identity" entry for places where the choice may stay unset
* (bookmarks), so changing the default later applies retroactively.
*/
final class IdentityChooser extends JComboBox<Object> {
private static final String USE_DEFAULT = "‹Default identity›";
IdentityChooser(IdentityStore identities, boolean allowDefault, String selectedId) {
if (allowDefault) addItem(USE_DEFAULT);
for (IdentityEntry e : identities.all()) addItem(e);
IdentityEntry selected = identities.byId(selectedId);
if (selected != null) {
setSelectedItem(selected);
} else if (allowDefault) {
setSelectedItem(USE_DEFAULT);
}
setRenderer(new DefaultListCellRenderer() {
@Override
public Component getListCellRendererComponent(JList<?> list, Object value, int index,
boolean isSelected, boolean cellHasFocus) {
String text = value instanceof IdentityEntry
? ((IdentityEntry) value).getName()
: String.valueOf(value);
return super.getListCellRendererComponent(list, text, index, isSelected, cellHasFocus);
}
});
}
/** Selected identity id, or an empty string when the default is to be used. */
String getSelectedIdentityId() {
Object v = getSelectedItem();
return v instanceof IdentityEntry ? ((IdentityEntry) v).getId() : "";
}
}