various: bump dependencies; wire up dead code

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I12432bc956453cc4b0a2db82dce1b4976a6a6964
This commit is contained in:
raf 2026-02-05 14:36:01 +03:00
commit 875bdf5ebc
Signed by: NotAShelf
GPG key ID: 29D95B64378DB4BF
6 changed files with 764 additions and 427 deletions

View file

@ -2,7 +2,7 @@ use dioxus::prelude::*;
use super::image_viewer::ImageViewer;
use super::markdown_viewer::MarkdownViewer;
use super::media_player::MediaPlayer;
use super::media_player::{MediaPlayer, PlayQueue, QueueItem, QueuePanel};
use super::pdf_viewer::PdfViewer;
use super::utils::{format_duration, format_size, media_category, type_badge_class};
use crate::client::{ApiClient, MediaResponse, MediaUpdateEvent, TagResponse};
@ -14,6 +14,7 @@ pub fn Detail(
all_tags: Vec<TagResponse>,
server_url: String,
#[props(default = false)] autoplay: bool,
#[props(default)] play_queue: Option<PlayQueue>,
on_back: EventHandler<()>,
on_open: EventHandler<String>,
on_update: EventHandler<MediaUpdateEvent>,
@ -22,6 +23,15 @@ pub fn Detail(
on_set_custom_field: EventHandler<(String, String, String, String)>,
on_delete_custom_field: EventHandler<(String, String)>,
on_delete: EventHandler<String>,
#[props(default)] on_queue_select: Option<EventHandler<usize>>,
#[props(default)] on_queue_remove: Option<EventHandler<usize>>,
#[props(default)] on_queue_clear: Option<EventHandler<()>>,
#[props(default)] on_queue_toggle_repeat: Option<EventHandler<()>>,
#[props(default)] on_queue_toggle_shuffle: Option<EventHandler<()>>,
#[props(default)] on_queue_next: Option<EventHandler<()>>,
#[props(default)] on_queue_previous: Option<EventHandler<()>>,
#[props(default)] on_track_ended: Option<EventHandler<()>>,
#[props(default)] on_add_to_queue: Option<EventHandler<QueueItem>>,
) -> Element {
let mut editing = use_signal(|| false);
let mut show_image_viewer = use_signal(|| false);
@ -225,6 +235,9 @@ pub fn Detail(
let thumb_for_player = thumbnail_url.clone();
let file_name_for_viewer = media.file_name.clone();
// Clone queue handlers for use in the component
let has_queue = play_queue.is_some();
rsx! {
// Media preview
div { class: "detail-preview",
@ -235,6 +248,7 @@ pub fn Detail(
title: media.title.clone(),
thumbnail_url: if has_thumbnail { Some(thumb_for_player.clone()) } else { None },
autoplay,
on_track_ended: on_track_ended,
}
} else if category == "video" {
MediaPlayer {
@ -242,6 +256,7 @@ pub fn Detail(
media_type: "video".to_string(),
title: media.title.clone(),
autoplay,
on_track_ended: on_track_ended,
}
} else if category == "image" {
if has_thumbnail {
@ -290,6 +305,71 @@ pub fn Detail(
}
}
// Play queue panel (only for audio/video with a queue)
if has_queue && (category == "audio" || category == "video") {
if let Some(ref queue) = play_queue {
QueuePanel {
queue: queue.clone(),
on_select: {
let handler = on_queue_select;
move |idx| {
if let Some(ref h) = handler {
h.call(idx);
}
}
},
on_remove: {
let handler = on_queue_remove;
move |idx| {
if let Some(ref h) = handler {
h.call(idx);
}
}
},
on_clear: {
let handler = on_queue_clear;
move |_| {
if let Some(ref h) = handler {
h.call(());
}
}
},
on_toggle_repeat: {
let handler = on_queue_toggle_repeat;
move |_| {
if let Some(ref h) = handler {
h.call(());
}
}
},
on_toggle_shuffle: {
let handler = on_queue_toggle_shuffle;
move |_| {
if let Some(ref h) = handler {
h.call(());
}
}
},
on_next: {
let handler = on_queue_next;
move |_| {
if let Some(ref h) = handler {
h.call(());
}
}
},
on_previous: {
let handler = on_queue_previous;
move |_| {
if let Some(ref h) = handler {
h.call(());
}
}
},
}
}
}
// Action bar
div { class: "detail-actions",
button {
@ -305,6 +385,46 @@ pub fn Detail(
},
"Open"
}
// Add to Queue button for audio/video content
if (category == "audio" || category == "video") && on_add_to_queue.is_some() {
{
// Check if this item is currently playing
let is_current = play_queue.as_ref()
.and_then(|q| q.current())
.map(|item| item.media_id == id)
.unwrap_or(false);
let media_id_for_queue = id.clone();
let title_for_queue = media.title.clone().unwrap_or_else(|| media.file_name.clone());
let artist_for_queue = media.artist.clone();
let duration_for_queue = media.duration_secs;
let media_type_for_queue = category.to_string();
let stream_url_for_queue = stream_url.clone();
let thumbnail_for_queue = if has_thumbnail { Some(thumbnail_url.clone()) } else { None };
let on_add = on_add_to_queue;
rsx! {
button {
class: if is_current { "btn btn-secondary disabled" } else { "btn btn-secondary" },
disabled: is_current,
title: if is_current { "Currently playing" } else { "Add to play queue" },
onclick: move |_| {
if let Some(ref handler) = on_add {
let item = QueueItem {
media_id: media_id_for_queue.clone(),
title: title_for_queue.clone(),
artist: artist_for_queue.clone(),
duration_secs: duration_for_queue,
media_type: media_type_for_queue.clone(),
stream_url: stream_url_for_queue.clone(),
thumbnail_url: thumbnail_for_queue.clone(),
};
handler.call(item);
}
},
if is_current { "\u{266b} Playing" } else { "\u{2795} Queue" }
}
}
}
}
if is_editing {
button { class: "btn btn-primary", onclick: on_save_click, "Save" }
button { class: "btn btn-ghost", onclick: on_cancel_click, "Cancel" }