Let a session reconnect to where it was

ServerSession.reconnect() connects again to the last server with the
same identity and returns to the channel the client was in: what a
dropped connection or a changed network (Android moving from Wi-Fi to
mobile data) needs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-25 08:26:03 +00:00
parent 07aa7bd7f9
commit 11a2a14c70

View File

@@ -56,6 +56,13 @@ public final class ServerSession {
private volatile boolean connecting; private volatile boolean connecting;
/** Identity used for the current connection, so it can be saved into a bookmark. */ /** Identity used for the current connection, so it can be saved into a bookmark. */
private volatile String identityId = ""; private volatile String identityId = "";
/** How the last connect was made, for {@link #reconnect}; null before the first one. */
private volatile Target lastTarget;
/** The channel we were in when the connection last went, to return to on a reconnect. */
private volatile String lastChannelPath = "";
private record Target(String address, int port, String nickname, String password, String channelPassword) {
}
private volatile boolean micMuted; private volatile boolean micMuted;
private volatile boolean micLocalMuted; private volatile boolean micLocalMuted;
@@ -120,6 +127,8 @@ public final class ServerSession {
if (isBusy()) return; if (isBusy()) return;
connecting = true; connecting = true;
} }
lastTarget = new Target(address, port, nickname, password, channelPassword);
lastChannelPath = channel == null ? "" : channel;
title = address + ":" + port; title = address + ":" + port;
listener.onSystemMessage("Connecting to " + address + ":" + port listener.onSystemMessage("Connecting to " + address + ":" + port
+ (channel == null || channel.isBlank() ? "" : " (channel \"" + channel + "\")") + " …"); + (channel == null || channel.isBlank() ? "" : " (channel \"" + channel + "\")") + " …");
@@ -158,6 +167,19 @@ public final class ServerSession {
}, "ts3j-switch-server").start(); }, "ts3j-switch-server").start();
} }
/**
* Connects again to the server of the last connect, with the same identity, returning to
* the channel we were in — for a connection that dropped, or a network that changed.
* Leaves the server first if still on it. Does nothing before a first connect.
*/
public void reconnect() {
Target target = lastTarget;
if (target == null) return;
String channel = conn.isConnected() ? currentChannelPath() : lastChannelPath;
switchTo(target.address(), target.port(), target.nickname(), target.password(), identityId,
channel, target.channelPassword());
}
public void disconnect() { public void disconnect() {
if (conn.isConnected()) conn.disconnect(); if (conn.isConnected()) conn.disconnect();
} }
@@ -393,6 +415,9 @@ public final class ServerSession {
@Override @Override
public void onModelChanged() { public void onModelChanged() {
// By the time a connection is reported gone, it no longer knows where we were.
String channel = currentChannelPath();
if (!channel.isEmpty()) lastChannelPath = channel;
String name = conn.getModel().getServerName(); String name = conn.getModel().getServerName();
if (conn.isConnected() && name != null && !name.isBlank() && !name.equals(title)) { if (conn.isConnected() && name != null && !name.isBlank() && !name.equals(title)) {
title = name; title = name;