fix: guard unsafe .first/.last calls to prevent StateError

This commit is contained in:
edde746
2026-03-10 03:50:12 +01:00
parent 42e066288f
commit 73fe9e054f
7 changed files with 25 additions and 16 deletions
@@ -226,6 +226,10 @@ class CompanionRemoteProvider with ChangeNotifier {
}
Future<void> joinSessionMulti(String sessionId, String pin, List<String> hostAddresses) async {
if (hostAddresses.isEmpty) {
throw ArgumentError('hostAddresses must not be empty');
}
await leaveSession();
_lastSessionId = sessionId;
+2 -2
View File
@@ -145,7 +145,7 @@ class OfflineWatchProvider extends ChangeNotifier {
}
// All episodes watched - return first episode for replay
return episodes.first;
return episodes.firstOrNull;
}
/// Find the next unwatched downloaded episode synchronously.
@@ -164,7 +164,7 @@ class OfflineWatchProvider extends ChangeNotifier {
}
// All episodes watched - return first episode for replay
return episodes.first;
return episodes.firstOrNull;
}
/// Emit a watch state change event for immediate UI update.
+2 -2
View File
@@ -210,7 +210,7 @@ class PlaybackStateProvider with ChangeNotifier {
}
// Need to load next window
if (_client != null && _playQueueId != null) {
if (_client != null && _playQueueId != null && _loadedItems.isNotEmpty) {
// Load next window centered on the item after current
final nextItemID = _loadedItems.last.playQueueItemID;
if (nextItemID != null) {
@@ -248,7 +248,7 @@ class PlaybackStateProvider with ChangeNotifier {
}
// Need to load previous window
if (_client != null && _playQueueId != null) {
if (_client != null && _playQueueId != null && _loadedItems.isNotEmpty) {
final prevItemID = _loadedItems.first.playQueueItemID;
if (prevItemID != null && prevItemID > 0) {
final loaded = await _ensureItemsLoaded(prevItemID - 1);
@@ -59,10 +59,10 @@ abstract class BaseMediaListDetailScreen<T extends StatefulWidget> extends State
// If serverId is null, fall back to first available server
if (serverId == null) {
final multiServerProvider = Provider.of<MultiServerProvider>(context, listen: false);
if (!multiServerProvider.hasConnectedServers) {
serverId = multiServerProvider.onlineServerIds.firstOrNull;
if (serverId == null) {
throw Exception(t.errors.noClientAvailable);
}
serverId = multiServerProvider.onlineServerIds.first;
}
return context.getClientForServer(serverId);
+6 -4
View File
@@ -63,10 +63,11 @@ class _DiscoverScreenState extends State<DiscoverScreen>
@override
PlexClient get client {
final multiServerProvider = Provider.of<MultiServerProvider>(context, listen: false);
if (!multiServerProvider.hasConnectedServers) {
final serverId = multiServerProvider.onlineServerIds.firstOrNull;
if (serverId == null) {
throw Exception('No servers available');
}
return context.getClientForServer(multiServerProvider.onlineServerIds.first);
return context.getClientForServer(serverId);
}
List<PlexMetadata> _onDeck = [];
@@ -140,10 +141,11 @@ class _DiscoverScreenState extends State<DiscoverScreen>
final serverId = item?.serverId;
if (serverId == null) {
final multiServerProvider = Provider.of<MultiServerProvider>(context, listen: false);
if (!multiServerProvider.hasConnectedServers) {
final fallbackId = multiServerProvider.onlineServerIds.firstOrNull;
if (fallbackId == null) {
throw Exception('No servers available');
}
return context.getClientForServer(multiServerProvider.onlineServerIds.first);
return context.getClientForServer(fallbackId);
}
return context.getClientForServer(serverId);
}
+3 -2
View File
@@ -79,10 +79,11 @@ class _LibrariesScreenState extends State<LibrariesScreen>
@override
PlexClient get client {
final multiServerProvider = Provider.of<MultiServerProvider>(context, listen: false);
if (!multiServerProvider.hasConnectedServers) {
final serverId = multiServerProvider.onlineServerIds.firstOrNull;
if (serverId == null) {
throw Exception(t.errors.noClientAvailable);
}
return context.getClientForServer(multiServerProvider.onlineServerIds.first);
return context.getClientForServer(serverId);
}
// GlobalKeys for tabs to enable refresh
+6 -4
View File
@@ -50,10 +50,11 @@ extension ProviderExtensions on BuildContext {
// If library doesn't have a serverId, fall back to first available server
if (library.serverId == null) {
final multiServerProvider = Provider.of<MultiServerProvider>(this, listen: false);
if (!multiServerProvider.hasConnectedServers) {
final serverId = multiServerProvider.onlineServerIds.firstOrNull;
if (serverId == null) {
throw Exception(t.errors.noClientAvailable);
}
return getClientForServer(multiServerProvider.onlineServerIds.first);
return getClientForServer(serverId);
}
return getClientForServer(library.serverId!);
}
@@ -80,10 +81,11 @@ extension ProviderExtensions on BuildContext {
/// Throws an exception if no servers are available
PlexClient getFirstAvailableClient() {
final multiServerProvider = Provider.of<MultiServerProvider>(this, listen: false);
if (!multiServerProvider.hasConnectedServers) {
final serverId = multiServerProvider.onlineServerIds.firstOrNull;
if (serverId == null) {
throw Exception(t.errors.noClientAvailable);
}
return getClientForServer(multiServerProvider.onlineServerIds.first);
return getClientForServer(serverId);
}
/// Get client for a serverId with fallback to first available server