From 141deb8da08d23fc1b49d2e0f9912ad2ce71f05a Mon Sep 17 00:00:00 2001 From: edde746 <86283021+edde746@users.noreply.github.com> Date: Tue, 25 Nov 2025 03:33:24 +0100 Subject: [PATCH] fix: profile switcher --- lib/providers/multi_server_provider.dart | 26 +++++++++ lib/providers/user_profile_provider.dart | 74 +++++++----------------- lib/screens/main_screen.dart | 28 +++++++-- 3 files changed, 71 insertions(+), 57 deletions(-) diff --git a/lib/providers/multi_server_provider.dart b/lib/providers/multi_server_provider.dart index 2b903654..a2f6fd08 100644 --- a/lib/providers/multi_server_provider.dart +++ b/lib/providers/multi_server_provider.dart @@ -3,6 +3,7 @@ import 'package:flutter/foundation.dart'; import '../client/plex_client.dart'; import '../services/data_aggregation_service.dart'; import '../services/multi_server_manager.dart'; +import '../services/plex_auth_service.dart'; import '../utils/app_logger.dart'; /// Provider for multi-server Plex connections @@ -70,6 +71,31 @@ class MultiServerProvider extends ChangeNotifier { notifyListeners(); } + /// Reconnect all servers after a profile switch + /// Clears existing connections and connects to all provided servers + Future reconnectWithServers( + List servers, { + String? clientIdentifier, + }) async { + // Clear existing connections first + _serverManager.disconnectAll(); + appLogger.d( + 'MultiServerProvider: Cleared connections, reconnecting to ${servers.length} servers', + ); + + // Connect with new server tokens + final connectedCount = await _serverManager.connectToAllServers( + servers, + clientIdentifier: clientIdentifier, + ); + + appLogger.i( + 'MultiServerProvider: Reconnected to $connectedCount/${servers.length} servers after profile switch', + ); + notifyListeners(); + return connectedCount; + } + /// Check server health for all connected servers Future checkServerHealth() async { await _serverManager.checkServerHealth(); diff --git a/lib/providers/user_profile_provider.dart b/lib/providers/user_profile_provider.dart index 03ddca58..f2cd9b46 100644 --- a/lib/providers/user_profile_provider.dart +++ b/lib/providers/user_profile_provider.dart @@ -34,18 +34,24 @@ class UserProfileProvider extends ChangeNotifier { StorageService? _storageService; // Callback for data invalidation when switching profiles - VoidCallback? _onDataInvalidationRequested; + // Receives the list of servers with new profile tokens for reconnection + Future Function(List)? _onDataInvalidationRequested; /// Set a callback to be called when profile switching requires data invalidation - void setDataInvalidationCallback(VoidCallback? callback) { + /// The callback receives the list of servers with the new profile's access tokens + void setDataInvalidationCallback( + Future Function(List)? callback, + ) { _onDataInvalidationRequested = callback; } - /// Trigger data invalidation for all screens - void _invalidateAllData() { + /// Trigger data invalidation for all screens with the new profile's servers + Future _invalidateAllData(List servers) async { if (_onDataInvalidationRequested != null) { - _onDataInvalidationRequested!(); - appLogger.d('Data invalidation triggered for profile switch'); + await _onDataInvalidationRequested!(servers); + appLogger.d( + 'Data invalidation triggered for profile switch with ${servers.length} servers', + ); } } @@ -294,7 +300,7 @@ class UserProfileProvider extends ChangeNotifier { ); // switchResponse.authToken is the new user's Plex.tv token - // We need to fetch servers with this token to get the proper server access token + // Fetch servers with this token to get the proper server access tokens appLogger.d('Got new user Plex.tv token, fetching servers...'); final servers = await _authService!.fetchServers( @@ -304,38 +310,14 @@ class UserProfileProvider extends ChangeNotifier { throw Exception('No servers available for this user'); } - // Find the current server from storage - final currentServerData = _storageService!.getServerData(); - if (currentServerData == null) { - throw Exception('No current server data found'); - } + appLogger.d('Fetched ${servers.length} servers for new profile'); - // Find matching server by name or client identifier - final currentServerName = currentServerData['name'] as String?; - final currentServerClientId = - currentServerData['clientIdentifier'] as String?; - - final matchingServer = servers.firstWhere( - (server) => - server.name == currentServerName || - server.clientIdentifier == currentServerClientId, - orElse: () => servers.first, // Fallback to first server - ); - - appLogger.d( - 'Found matching server: ${matchingServer.name}, getting access token', - ); - - // Update storage with new tokens - await _storageService!.updateCurrentUser( - user.uuid, - matchingServer - .accessToken, // Use server access token, not Plex.tv token - ); - - // Also save the new Plex.tv token for future profile operations + // Save the new Plex.tv token for future profile operations await _storageService!.savePlexToken(switchResponse.authToken); + // Update current user UUID in storage + await _storageService!.saveCurrentUserUUID(user.uuid); + // Update current user _currentUser = user; @@ -351,26 +333,14 @@ class UserProfileProvider extends ChangeNotifier { }, ); - // Update PlexClient with proper server access token - if (clientProvider != null) { - try { - clientProvider.updateToken(matchingServer.accessToken); - appLogger.d( - 'Updated PlexClient with server access token for user: ${user.displayName}', - ); - } catch (e) { - appLogger.w('Failed to update PlexClient token', error: e); - } - } - notifyListeners(); - // Invalidate all cached data for the new profile - // This will cause screens to refresh and rebuild widgets with the new token - _invalidateAllData(); + // Invalidate all cached data and reconnect to all servers with new tokens + // The callback will handle server reconnection using the servers list + await _invalidateAllData(servers); appLogger.d( - 'Profile switch complete, all data and images should refresh with new token', + 'Profile switch complete, all servers reconnected with new tokens', ); appLogger.i('Successfully switched to user: ${user.displayName}'); diff --git a/lib/screens/main_screen.dart b/lib/screens/main_screen.dart index 1e06635c..19e75bef 100644 --- a/lib/screens/main_screen.dart +++ b/lib/screens/main_screen.dart @@ -10,6 +10,8 @@ import '../providers/multi_server_provider.dart'; import '../providers/server_state_provider.dart'; import '../providers/hidden_libraries_provider.dart'; import '../providers/playback_state_provider.dart'; +import '../services/plex_auth_service.dart'; +import '../services/storage_service.dart'; import 'discover_screen.dart'; import 'libraries_screen.dart'; import 'search_screen.dart'; @@ -96,17 +98,33 @@ class _MainScreenState extends State with RouteAware { } /// Invalidate all cached data across all screens when profile is switched - void _invalidateAllScreens() { - appLogger.d('Invalidating all screen data due to profile switch'); + /// Receives the list of servers with new profile tokens for reconnection + Future _invalidateAllScreens(List servers) async { + appLogger.d( + 'Invalidating all screen data due to profile switch with ${servers.length} servers', + ); - // Clear all provider states first (servers, playback, UI state) + // Get all providers final multiServerProvider = context.read(); final serverStateProvider = context.read(); final hiddenLibrariesProvider = context.read(); final playbackStateProvider = context.read(); - // Clear all server connections (new profile may have different servers) - multiServerProvider.clearAllConnections(); + // Reconnect to all servers with new profile tokens + if (servers.isNotEmpty) { + final storage = await StorageService.getInstance(); + final clientId = storage.getClientIdentifier(); + + final connectedCount = await multiServerProvider.reconnectWithServers( + servers, + clientIdentifier: clientId, + ); + appLogger.d( + 'Reconnected to $connectedCount/${servers.length} servers after profile switch', + ); + } + + // Reset other provider states serverStateProvider.reset(); hiddenLibrariesProvider.refresh(); playbackStateProvider.clearShuffle();