Merge branch 'fix-plex-notifications'
This commit is contained in:
@@ -97,6 +97,7 @@ class _AuthScreenState extends State<AuthScreen> {
|
||||
multiServerProvider: context.read<MultiServerProvider>(),
|
||||
librariesProvider: context.read<LibrariesProvider>(),
|
||||
syncService: context.read<OfflineWatchSyncService>(),
|
||||
clientIdentifier: _authService.clientIdentifier,
|
||||
);
|
||||
|
||||
if (!result.hasConnections) {
|
||||
|
||||
@@ -83,7 +83,7 @@ class MultiServerManager {
|
||||
final cachedEndpoint = storage.getServerEndpoint(serverId);
|
||||
|
||||
// Find best working connection, passing cached endpoint for fast-path
|
||||
final streamIterator = StreamIterator(server.findBestWorkingConnection(preferredUri: cachedEndpoint));
|
||||
final streamIterator = StreamIterator(server.findBestWorkingConnection(preferredUri: cachedEndpoint, clientIdentifier: clientIdentifier));
|
||||
|
||||
if (!await streamIterator.moveNext()) {
|
||||
throw Exception('No working connection found');
|
||||
@@ -388,7 +388,7 @@ class MultiServerManager {
|
||||
try {
|
||||
appLogger.d('Starting connection optimization for ${server.name}', error: {'reason': reason});
|
||||
|
||||
await for (final connection in server.findBestWorkingConnection(preferredUri: cachedEndpoint)) {
|
||||
await for (final connection in server.findBestWorkingConnection(preferredUri: cachedEndpoint, clientIdentifier: _clientIdentifier)) {
|
||||
final newUrl = connection.uri;
|
||||
|
||||
// Check if this is actually a better connection than current
|
||||
|
||||
@@ -391,7 +391,7 @@ class PlexServer {
|
||||
/// Priority: local > remote > relay, then HTTPS > HTTP, then lowest latency
|
||||
/// Tests both plex.direct URI and direct IP for each connection
|
||||
/// HTTPS connections are tested first, with HTTP as fallback
|
||||
Stream<PlexConnection> findBestWorkingConnection({String? preferredUri}) async* {
|
||||
Stream<PlexConnection> findBestWorkingConnection({String? preferredUri, String? clientIdentifier}) async* {
|
||||
if (connections.isEmpty) {
|
||||
appLogger.w('No connections available for server discovery');
|
||||
return;
|
||||
@@ -437,6 +437,7 @@ class PlexServer {
|
||||
cachedCandidate.url,
|
||||
accessToken,
|
||||
timeout: preferredTimeout,
|
||||
clientIdentifier: clientIdentifier,
|
||||
);
|
||||
|
||||
if (result.success) {
|
||||
@@ -456,7 +457,7 @@ class PlexServer {
|
||||
appLogger.d('Running connection race to find first working endpoint', error: {'candidateCount': totalCandidates});
|
||||
|
||||
for (final candidate in candidates) {
|
||||
PlexClient.testConnectionWithLatency(candidate.url, accessToken, timeout: raceTimeout).then((result) {
|
||||
PlexClient.testConnectionWithLatency(candidate.url, accessToken, timeout: raceTimeout, clientIdentifier: clientIdentifier).then((result) {
|
||||
completedTests++;
|
||||
|
||||
if (!result.success) {
|
||||
@@ -501,7 +502,7 @@ class PlexServer {
|
||||
}
|
||||
|
||||
// Attempt HTTPS upgrade on the Phase 1 winner before emitting
|
||||
final upgradedFirstCandidate = await _upgradeCandidateToHttpsIfPossible(firstCandidate);
|
||||
final upgradedFirstCandidate = await _upgradeCandidateToHttpsIfPossible(firstCandidate, clientIdentifier: clientIdentifier);
|
||||
final emitCandidate = upgradedFirstCandidate ?? firstCandidate;
|
||||
|
||||
final firstConnection = _updateConnectionUrl(emitCandidate.connection, emitCandidate.url);
|
||||
@@ -523,7 +524,7 @@ class PlexServer {
|
||||
|
||||
await Future.wait(
|
||||
candidates.map((candidate) async {
|
||||
final result = await PlexClient.testConnectionWithAverageLatency(candidate.url, accessToken, attempts: 2);
|
||||
final result = await PlexClient.testConnectionWithAverageLatency(candidate.url, accessToken, attempts: 2, clientIdentifier: clientIdentifier);
|
||||
|
||||
if (result.success) {
|
||||
candidateResults[candidate] = result;
|
||||
@@ -547,7 +548,7 @@ class PlexServer {
|
||||
|
||||
// Emit the best connection if it's different from the first one
|
||||
if (bestCandidate != null) {
|
||||
final upgradedCandidate = await _upgradeCandidateToHttpsIfPossible(bestCandidate) ?? bestCandidate;
|
||||
final upgradedCandidate = await _upgradeCandidateToHttpsIfPossible(bestCandidate, clientIdentifier: clientIdentifier) ?? bestCandidate;
|
||||
|
||||
final bestConnection = _updateConnectionUrl(upgradedCandidate.connection, upgradedCandidate.url);
|
||||
if (bestConnection.uri != firstConnection.uri) {
|
||||
@@ -665,7 +666,7 @@ class PlexServer {
|
||||
return urls;
|
||||
}
|
||||
|
||||
Future<_ConnectionCandidate?> _upgradeCandidateToHttpsIfPossible(_ConnectionCandidate candidate) async {
|
||||
Future<_ConnectionCandidate?> _upgradeCandidateToHttpsIfPossible(_ConnectionCandidate candidate, {String? clientIdentifier}) async {
|
||||
final currentUrl = candidate.url;
|
||||
if (currentUrl.startsWith('https://')) {
|
||||
return null;
|
||||
@@ -715,6 +716,7 @@ class PlexServer {
|
||||
httpsUrl,
|
||||
accessToken,
|
||||
timeout: ConnectionTimeouts.connectionRace,
|
||||
clientIdentifier: clientIdentifier,
|
||||
);
|
||||
|
||||
if (!result.success) {
|
||||
|
||||
@@ -216,6 +216,7 @@ class PlexClient {
|
||||
String baseUrl,
|
||||
String token, {
|
||||
Duration timeout = const Duration(seconds: 5),
|
||||
String? clientIdentifier,
|
||||
}) async {
|
||||
final stopwatch = Stopwatch()..start();
|
||||
|
||||
@@ -231,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'] = 'Plezy';
|
||||
headers['X-Plex-Device-Name'] = 'Plezy';
|
||||
}
|
||||
|
||||
final response = await dio.get('/', options: Options(headers: headers));
|
||||
|
||||
stopwatch.stop();
|
||||
final success = response.statusCode == 200;
|
||||
@@ -267,11 +275,17 @@ class PlexClient {
|
||||
String token, {
|
||||
int attempts = 3,
|
||||
Duration timeout = const Duration(seconds: 5),
|
||||
String? clientIdentifier,
|
||||
}) 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,
|
||||
);
|
||||
|
||||
// If any attempt fails, return failed result immediately
|
||||
if (!result.success) {
|
||||
|
||||
Reference in New Issue
Block a user