From ba40d07f73e83bc273d949e72972974cef8cc371 Mon Sep 17 00:00:00 2001 From: Eric Coissac Date: Sun, 7 Jun 2026 14:40:22 +0200 Subject: [PATCH] fix: prevent direct playback of single-item playlists Update `isNavigable` to explicitly validate `item.is_container` and disable navigation for playlists with only one item. This forces users to enter the playlist container, preserving metadata update benefits. --- pmoapp/webapp/src/components/unified/ServerDrawer.vue | 8 ++++++-- pmocontrol/src/media_server.rs | 3 +++ pmocontrol/src/pmoserver_ext.rs | 4 ++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/pmoapp/webapp/src/components/unified/ServerDrawer.vue b/pmoapp/webapp/src/components/unified/ServerDrawer.vue index 035d41e6..0ed350cf 100644 --- a/pmoapp/webapp/src/components/unified/ServerDrawer.vue +++ b/pmoapp/webapp/src/components/unified/ServerDrawer.vue @@ -289,8 +289,12 @@ function isPlayable(item: ContainerEntry): boolean { // Détermine si un container est navigable function isNavigable(item: ContainerEntry): boolean { - // Tous les containers sont navigables (on laisse le serveur décider si vide) - return item.is_container; + if (!item.is_container) return false; + // Une playlist avec un seul item : on garde le caractère jouable mais on retire + // la navigation pour éviter que l'utilisateur joue l'item directement et perde + // le bénéfice des mises à jour de métadonnées de la playlist. + if (isPlayable(item) && item.child_count === 1) return false; + return true; } function handleItemClick(item: ContainerEntry) { diff --git a/pmocontrol/src/media_server.rs b/pmocontrol/src/media_server.rs index d813d2d3..e82343f7 100644 --- a/pmocontrol/src/media_server.rs +++ b/pmocontrol/src/media_server.rs @@ -373,6 +373,7 @@ pub struct MediaEntry { pub is_container: bool, pub class: String, pub resources: Vec, + pub child_count: Option, pub artist: Option, pub album: Option, pub genre: Option, @@ -709,6 +710,7 @@ fn map_didl_entries(xml: &str) -> Result, ControlPointError> { is_container: true, class: container.class, resources: Vec::new(), + child_count: container.child_count.as_deref().and_then(|s| s.parse().ok()), artist: container.artist, album: None, genre: None, @@ -742,6 +744,7 @@ fn map_didl_entries(xml: &str) -> Result, ControlPointError> { is_container: false, class: item.class, resources, + child_count: None, artist: item.artist, album: item.album, genre: item.genre, diff --git a/pmocontrol/src/pmoserver_ext.rs b/pmocontrol/src/pmoserver_ext.rs index 883e9867..1bcfdce4 100644 --- a/pmocontrol/src/pmoserver_ext.rs +++ b/pmocontrol/src/pmoserver_ext.rs @@ -2211,7 +2211,7 @@ async fn browse_container( title: e.title, class: e.class, is_container: e.is_container, - child_count: None, + child_count: e.child_count, artist: e.artist, album: e.album, album_art_uri, @@ -2496,7 +2496,7 @@ async fn search_server( title: e.title, class: e.class, is_container: e.is_container, - child_count: None, + child_count: e.child_count, artist: e.artist, album: e.album, album_art_uri: e.album_art_uri,