Implémentation du menu déroulant pour les actions d'éléments dans le ServerDrawer
Ajout d'un menu déroulant avec les actions 'Ajouter à la queue' et 'Ajouter après' pour les éléments dans le ServerDrawer. - Remplacement des fonctions handlePlayItem et handleQueueItem par des fonctions plus spécifiques (handlePlayItem, handleAddToQueue, handleAddAfterCurrent) - Ajout d'une gestion du menu déroulant avec ouverture/fermeture - Intégration du composant useRenderers pour les actions de lecture - Mise à jour des styles pour le menu déroulant avec animations - Correction de l'alignement du backdrop sur mobile - Amélioration des transitions et animations du drawer - Ajout de la fonction addAfterCurrent dans l'API et le control point - Support de l'ajout d'éléments après le morceau actuel dans les queues
This commit is contained in:
@@ -38,7 +38,7 @@ use crate::{PlaybackItem, QueueSnapshot, errors::ControlPointError};
|
||||
pub enum EnqueueMode {
|
||||
/// Append new items at the end of the queue.
|
||||
AppendToEnd,
|
||||
/// Insert new items immediately after the current index
|
||||
/// Insert new items immediately after the current playing index
|
||||
/// (or at the beginning if there is no current index).
|
||||
InsertAfterCurrent,
|
||||
/// Replace the whole queue with the new items.
|
||||
@@ -161,7 +161,7 @@ pub trait QueueBackend {
|
||||
|
||||
/// Returns the current item (or the first pending item if no index is set)
|
||||
/// along with the count of remaining items.
|
||||
fn peek_current(&self) -> Result<Option<(PlaybackItem, usize)>, ControlPointError> {
|
||||
fn peek_current(&mut self) -> Result<Option<(PlaybackItem, usize)>, ControlPointError> {
|
||||
let snapshot = self.queue_snapshot()?;
|
||||
let QueueSnapshot {
|
||||
items,
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
//! - maintains a `current_index`,
|
||||
//! - never starts playback (transport control is handled elsewhere).
|
||||
|
||||
|
||||
use crate::{
|
||||
DeviceId, DeviceIdentity, RendererInfo,
|
||||
errors::ControlPointError,
|
||||
@@ -72,27 +71,16 @@ impl QueueBackend for InternalQueue {
|
||||
}
|
||||
|
||||
fn position_to_id(&self, id: usize) -> Result<u32, ControlPointError> {
|
||||
u32::try_from(id).map_err(|_| {
|
||||
ControlPointError::QueueError(format!(
|
||||
"Position {} exceeds u32::MAX",
|
||||
id
|
||||
))
|
||||
})
|
||||
u32::try_from(id)
|
||||
.map_err(|_| ControlPointError::QueueError(format!("Position {} exceeds u32::MAX", id)))
|
||||
}
|
||||
|
||||
fn current_track(&self) -> Result<Option<u32>, ControlPointError> {
|
||||
match self.current_index {
|
||||
None => Ok(None),
|
||||
Some(i) => {
|
||||
u32::try_from(i)
|
||||
.map(Some)
|
||||
.map_err(|_| {
|
||||
ControlPointError::QueueError(format!(
|
||||
"Current index {} exceeds u32::MAX",
|
||||
i
|
||||
))
|
||||
})
|
||||
}
|
||||
Some(i) => u32::try_from(i).map(Some).map_err(|_| {
|
||||
ControlPointError::QueueError(format!("Current index {} exceeds u32::MAX", i))
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,16 +130,14 @@ impl QueueBackend for InternalQueue {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn sync_queue(
|
||||
&mut self,
|
||||
items: Vec<PlaybackItem>
|
||||
) -> Result<(), ControlPointError> {
|
||||
fn sync_queue(&mut self, items: Vec<PlaybackItem>) -> Result<(), ControlPointError> {
|
||||
if items.is_empty() {
|
||||
return self.replace_queue(Vec::new(), None);
|
||||
}
|
||||
|
||||
// Récupérer l'item actuel
|
||||
let current = self.current_index
|
||||
let current = self
|
||||
.current_index
|
||||
.and_then(|idx| self.items.get(idx).map(|item| (idx, item.uri.clone())));
|
||||
|
||||
if let Some((_current_idx, current_uri)) = current {
|
||||
@@ -187,7 +173,8 @@ impl QueueBackend for InternalQueue {
|
||||
self.items.extend(items);
|
||||
}
|
||||
EnqueueMode::InsertAfterCurrent => {
|
||||
let insert_pos = self.current_index
|
||||
let insert_pos = self
|
||||
.current_index
|
||||
.map(|i| (i + 1).min(self.items.len()))
|
||||
.unwrap_or(0);
|
||||
|
||||
@@ -242,7 +229,7 @@ impl QueueBackend for InternalQueue {
|
||||
Ok(items)
|
||||
}
|
||||
|
||||
fn peek_current(&self) -> Result<Option<(PlaybackItem, usize)>, ControlPointError> {
|
||||
fn peek_current(&mut self) -> Result<Option<(PlaybackItem, usize)>, ControlPointError> {
|
||||
if self.items.is_empty() {
|
||||
return Ok(None);
|
||||
}
|
||||
@@ -250,7 +237,11 @@ impl QueueBackend for InternalQueue {
|
||||
let len = self.items.len();
|
||||
let (item, resolved_index) = match self.current_index {
|
||||
Some(idx) if idx < len => (self.items.get(idx).cloned(), Some(idx)),
|
||||
_ => (self.items.first().cloned(), None),
|
||||
_ => {
|
||||
// Si current_index est None ou invalide, initialiser à 0
|
||||
self.current_index = Some(0);
|
||||
(self.items.first().cloned(), Some(0))
|
||||
}
|
||||
};
|
||||
|
||||
let item = match item {
|
||||
|
||||
@@ -156,7 +156,7 @@ impl QueueBackend for MusicQueue {
|
||||
}
|
||||
}
|
||||
|
||||
fn peek_current(&self) -> Result<Option<(PlaybackItem, usize)>, ControlPointError> {
|
||||
fn peek_current(&mut self) -> Result<Option<(PlaybackItem, usize)>, ControlPointError> {
|
||||
match self {
|
||||
MusicQueue::Internal(q) => q.peek_current(),
|
||||
MusicQueue::OpenHome(q) => q.peek_current(),
|
||||
|
||||
@@ -778,7 +778,7 @@ impl QueueBackend for OpenHomeQueue {
|
||||
}
|
||||
|
||||
/// Optimized peek_current: use primitives instead of full snapshot.
|
||||
fn peek_current(&self) -> Result<Option<(PlaybackItem, usize)>, ControlPointError> {
|
||||
fn peek_current(&mut self) -> Result<Option<(PlaybackItem, usize)>, ControlPointError> {
|
||||
let len = self.len()?;
|
||||
if len == 0 {
|
||||
return Ok(None);
|
||||
|
||||
Reference in New Issue
Block a user