Fix duplicate Plex notifications and Flutter app name on login

Connection probe requests in testConnectionWithLatency were sent without
X-Plex-Client-Identifier, X-Plex-Product, or X-Plex-Device-Name headers.
Plex treated each anonymous probe as a new unknown device and fired a
"New Device" notification for every server tested (one per shared/owned
server), while displaying "Flutter" as the device name from the HTTP
user-agent.

Pass clientIdentifier through findBestWorkingConnection and all connection
test helpers so every probe request identifies itself as "Plezy" with the
persistent client UUID. This prevents spurious notifications and ensures
the device shows the correct app name in Plex's device list.

https://claude.ai/code/session_01V5VraujkNmk5GGPLyZ33fN
This commit is contained in:
Matt Vogel
2026-02-26 08:21:06 -05:00
parent 2b5923d80b
commit e9218e0a3d
3 changed files with 29 additions and 10 deletions
+19 -2
View File
@@ -215,6 +215,8 @@ class PlexClient {
String baseUrl,
String token, {
Duration timeout = const Duration(seconds: 5),
String? clientIdentifier,
String appName = 'Plezy',
}) async {
final stopwatch = Stopwatch()..start();
@@ -230,7 +232,14 @@ class PlexClient {
),
);
final response = await dio.get('/', options: Options(headers: {'X-Plex-Token': token}));
final headers = <String, String>{'X-Plex-Token': token};
if (clientIdentifier != null) {
headers['X-Plex-Client-Identifier'] = clientIdentifier;
headers['X-Plex-Product'] = appName;
headers['X-Plex-Device-Name'] = appName;
}
final response = await dio.get('/', options: Options(headers: headers));
stopwatch.stop();
final success = response.statusCode == 200;
@@ -266,11 +275,19 @@ class PlexClient {
String token, {
int attempts = 3,
Duration timeout = const Duration(seconds: 5),
String? clientIdentifier,
String appName = 'Plezy',
}) async {
final results = <ConnectionTestResult>[];
for (int i = 0; i < attempts; i++) {
final result = await testConnectionWithLatency(baseUrl, token, timeout: timeout);
final result = await testConnectionWithLatency(
baseUrl,
token,
timeout: timeout,
clientIdentifier: clientIdentifier,
appName: appName,
);
// If any attempt fails, return failed result immediately
if (!result.success) {