fix: make PlexMetadata type/key/title nullable for folder items

Plex API returns Directory entries without type field, causing
TypeError crash in fromJson. Made fields nullable and migrated
callers to use mediaType enum and displayTitle getter instead
of raw string access.
This commit is contained in:
edde746
2026-03-14 05:40:14 +01:00
parent 642c49b1ea
commit 4f736c555b
27 changed files with 134 additions and 140 deletions
+9 -16
View File
@@ -42,21 +42,14 @@ class FolderTreeItem extends StatelessWidget {
}
// File icons based on type
final type = item.type.toLowerCase();
switch (type) {
case 'movie':
return Symbols.movie_rounded;
case 'show':
return Symbols.tv_rounded;
case 'season':
return Symbols.video_library_rounded;
case 'episode':
return Symbols.play_circle_rounded;
case 'collection':
return Symbols.collections_rounded;
default:
return Symbols.insert_drive_file_rounded;
}
return switch (item.mediaType) {
PlexMediaType.movie => Symbols.movie_rounded,
PlexMediaType.show => Symbols.tv_rounded,
PlexMediaType.season => Symbols.video_library_rounded,
PlexMediaType.episode => Symbols.play_circle_rounded,
PlexMediaType.collection => Symbols.collections_rounded,
_ => Symbols.insert_drive_file_rounded,
};
}
void _handleTap() {
@@ -104,7 +97,7 @@ class FolderTreeItem extends StatelessWidget {
// Item title
Expanded(
child: Text(
item.title,
item.displayTitle,
style: TextStyle(fontSize: 14, fontWeight: isFolder ? FontWeight.w500 : FontWeight.w400),
maxLines: 1,
overflow: TextOverflow.ellipsis,
+14 -14
View File
@@ -87,32 +87,32 @@ class _FolderTreeViewState extends State<FolderTreeView> {
Future<void> _loadFolderChildren(PlexMetadata folder) async {
// Already loading this folder
if (_loadingFolders.contains(folder.key)) return;
if (_loadingFolders.contains(folder.key!)) return;
// Already loaded and cached
if (_childrenCache.containsKey(folder.key)) {
if (_childrenCache.containsKey(folder.key!)) {
setState(() {
_expandedFolders.add(folder.key);
_expandedFolders.add(folder.key!);
});
return;
}
setState(() {
_loadingFolders.add(folder.key);
_loadingFolders.add(folder.key!);
});
try {
final client = context.getClientForServer(widget.serverId!);
// Items are automatically tagged with server info by PlexClient
final children = await client.getFolderChildren(folder.key);
final children = await client.getFolderChildren(folder.key!);
if (!mounted) return;
setState(() {
_childrenCache[folder.key] = children;
_expandedFolders.add(folder.key);
_loadingFolders.remove(folder.key);
_childrenCache[folder.key!] = children;
_expandedFolders.add(folder.key!);
_loadingFolders.remove(folder.key!);
});
appLogger.d('Loaded ${children.length} children for folder: ${folder.title}');
@@ -121,7 +121,7 @@ class _FolderTreeViewState extends State<FolderTreeView> {
appLogger.e('Failed to load folder children', error: e);
setState(() {
_loadingFolders.remove(folder.key);
_loadingFolders.remove(folder.key!);
});
if (mounted) {
@@ -131,9 +131,9 @@ class _FolderTreeViewState extends State<FolderTreeView> {
}
void _toggleFolder(PlexMetadata folder) {
if (_expandedFolders.contains(folder.key)) {
if (_expandedFolders.contains(folder.key!)) {
setState(() {
_expandedFolders.remove(folder.key);
_expandedFolders.remove(folder.key!);
});
} else {
_loadFolderChildren(folder);
@@ -147,19 +147,19 @@ class _FolderTreeViewState extends State<FolderTreeView> {
Future<void> _handleFolderPlay(PlexMetadata folder) async {
final client = context.getClientForServer(widget.serverId!);
final launcher = PlayQueueLauncher(context: context, client: client, serverId: widget.serverId);
await launcher.launchFromFolder(folderKey: folder.key, shuffle: false);
await launcher.launchFromFolder(folderKey: folder.key!, shuffle: false);
}
Future<void> _handleFolderShuffle(PlexMetadata folder) async {
final client = context.getClientForServer(widget.serverId!);
final launcher = PlayQueueLauncher(context: context, client: client, serverId: widget.serverId);
await launcher.launchFromFolder(folderKey: folder.key, shuffle: true);
await launcher.launchFromFolder(folderKey: folder.key!, shuffle: true);
}
bool _isFolder(PlexMetadata item) {
// Folders typically don't have a specific type or might have special indicators
// Check for common folder indicators
return item.key.contains('/folder') || item.type.isEmpty || item.type.toLowerCase() == 'folder';
return item.key?.contains('/folder') == true || item.type == null || item.type!.isEmpty || item.mediaType == PlexMediaType.unknown;
}
List<Widget> _buildTreeItems(List<PlexMetadata> items, int depth, [String parentPath = '']) {