fix: profile switcher

This commit is contained in:
edde746
2025-11-25 03:33:30 +01:00
parent 4bcdb01029
commit 141deb8da0
3 changed files with 71 additions and 57 deletions
+26
View File
@@ -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<int> reconnectWithServers(
List<PlexServer> 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<void> checkServerHealth() async {
await _serverManager.checkServerHealth();
+22 -52
View File
@@ -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<void> Function(List<PlexServer>)? _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<void> Function(List<PlexServer>)? callback,
) {
_onDataInvalidationRequested = callback;
}
/// Trigger data invalidation for all screens
void _invalidateAllData() {
/// Trigger data invalidation for all screens with the new profile's servers
Future<void> _invalidateAllData(List<PlexServer> 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}');
+23 -5
View File
@@ -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<MainScreen> 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<void> _invalidateAllScreens(List<PlexServer> 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<MultiServerProvider>();
final serverStateProvider = context.read<ServerStateProvider>();
final hiddenLibrariesProvider = context.read<HiddenLibrariesProvider>();
final playbackStateProvider = context.read<PlaybackStateProvider>();
// 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();