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

@ -6,7 +6,9 @@ use futures::future::join_all;
use crate::client::*;
use crate::components::{
audit, collections, database, detail, duplicates, import, library, search, settings, tags,
audit, collections, database, detail, duplicates, import, library,
media_player::PlayQueue,
search, settings, statistics, tags, tasks,
};
// Login component available via crate::components::login when auth gating is needed
use crate::styles;
@ -23,6 +25,8 @@ enum View {
Audit,
Import,
Duplicates,
Statistics,
Tasks,
Settings,
Database,
}
@ -38,6 +42,8 @@ impl View {
Self::Audit => "Audit Log",
Self::Import => "Import",
Self::Duplicates => "Duplicates",
Self::Statistics => "Statistics",
Self::Tasks => "Tasks",
Self::Settings => "Settings",
Self::Database => "Database",
}
@ -68,6 +74,8 @@ pub fn App() -> Element {
let mut audit_list = use_signal(Vec::<AuditEntryResponse>::new);
let mut config_data = use_signal(|| Option::<ConfigResponse>::None);
let mut db_stats = use_signal(|| Option::<crate::client::DatabaseStatsResponse>::None);
let mut library_stats = use_signal(|| Option::<crate::client::LibraryStatisticsResponse>::None);
let mut scheduled_tasks = use_signal(Vec::<crate::client::ScheduledTaskResponse>::new);
let mut duplicate_groups = use_signal(Vec::<crate::client::DuplicateGroupResponse>::new);
let mut preview_files = use_signal(Vec::<DirectoryPreviewFile>::new);
let mut preview_total_size = use_signal(|| 0u64);
@ -111,6 +119,7 @@ pub fn App() -> Element {
let mut login_error = use_signal(|| Option::<String>::None);
let mut login_loading = use_signal(|| false);
let mut auto_play_media = use_signal(|| false);
let mut play_queue = use_signal(PlayQueue::default);
// Theme state (Phase 3.3)
let mut current_theme = use_signal(|| "dark".to_string());
@ -538,6 +547,40 @@ pub fn App() -> Element {
span { class: "nav-icon", "\u{2261}" }
span { class: "nav-item-text", "Duplicates" }
}
button {
class: if *current_view.read() == View::Statistics { "nav-item active" } else { "nav-item" },
onclick: {
let client = client.read().clone();
move |_| {
current_view.set(View::Statistics);
let client = client.clone();
spawn(async move {
if let Ok(stats) = client.library_statistics().await {
library_stats.set(Some(stats));
}
});
}
},
span { class: "nav-icon", "\u{1f4ca}" }
span { class: "nav-item-text", "Statistics" }
}
button {
class: if *current_view.read() == View::Tasks { "nav-item active" } else { "nav-item" },
onclick: {
let client = client.read().clone();
move |_| {
current_view.set(View::Tasks);
let client = client.clone();
spawn(async move {
if let Ok(tasks_data) = client.list_scheduled_tasks().await {
scheduled_tasks.set(tasks_data);
}
});
}
},
span { class: "nav-icon", "\u{23f0}" }
span { class: "nav-item-text", "Tasks" }
}
button {
class: if *current_view.read() == View::Settings { "nav-item active" } else { "nav-item" },
onclick: {
@ -1175,6 +1218,98 @@ pub fn App() -> Element {
});
}
},
play_queue: if play_queue.read().is_empty() { None } else { Some(play_queue.read().clone()) },
on_queue_select: {
move |idx: usize| {
let mut q = play_queue.write();
q.current_index = idx;
// Update selected_media to the item at this index
if let Some(item) = q.items.get(idx) {
let media_id = item.media_id.clone();
let client = client.read().clone();
spawn(async move {
if let Ok(media) = client.get_media(&media_id).await {
selected_media.set(Some(media));
auto_play_media.set(true);
}
});
}
}
},
on_queue_remove: {
move |idx: usize| {
play_queue.write().remove(idx);
}
},
on_queue_clear: {
move |_| {
play_queue.write().clear();
}
},
on_queue_toggle_repeat: {
move |_| {
play_queue.write().toggle_repeat();
}
},
on_queue_toggle_shuffle: {
move |_| {
play_queue.write().toggle_shuffle();
}
},
on_queue_next: {
move |_| {
let mut q = play_queue.write();
if let Some(item) = q.next() {
let media_id = item.media_id.clone();
drop(q);
let client = client.read().clone();
spawn(async move {
if let Ok(media) = client.get_media(&media_id).await {
selected_media.set(Some(media));
auto_play_media.set(true);
}
});
}
}
},
on_queue_previous: {
move |_| {
let mut q = play_queue.write();
if let Some(item) = q.previous() {
let media_id = item.media_id.clone();
drop(q);
let client = client.read().clone();
spawn(async move {
if let Ok(media) = client.get_media(&media_id).await {
selected_media.set(Some(media));
auto_play_media.set(true);
}
});
}
}
},
on_track_ended: {
move |_| {
let mut q = play_queue.write();
if let Some(item) = q.next() {
let media_id = item.media_id.clone();
drop(q);
let client = client.read().clone();
spawn(async move {
if let Ok(media) = client.get_media(&media_id).await {
selected_media.set(Some(media));
auto_play_media.set(true);
}
});
}
}
},
on_add_to_queue: {
move |item: crate::components::media_player::QueueItem| {
play_queue.write().add(item);
show_toast("Added to queue".into(), false);
}
},
}
},
None => rsx! {
@ -1979,6 +2114,86 @@ pub fn App() -> Element {
}
}
}
View::Statistics => {
let refresh_stats = {
let client = client.read().clone();
move || {
let client = client.clone();
spawn(async move {
match client.library_statistics().await {
Ok(stats) => library_stats.set(Some(stats)),
Err(e) => show_toast(format!("Failed to load statistics: {e}"), true),
}
});
}
};
rsx! {
statistics::Statistics {
stats: library_stats.read().clone(),
on_refresh: {
let refresh_stats = refresh_stats.clone();
move |_| refresh_stats()
},
}
}
}
View::Tasks => {
let refresh_tasks = {
let client = client.read().clone();
move || {
let client = client.clone();
spawn(async move {
match client.list_scheduled_tasks().await {
Ok(tasks_data) => scheduled_tasks.set(tasks_data),
Err(e) => show_toast(format!("Failed to load tasks: {e}"), true),
}
});
}
};
rsx! {
tasks::Tasks {
tasks: scheduled_tasks.read().clone(),
on_refresh: {
let refresh_tasks = refresh_tasks.clone();
move |_| refresh_tasks()
},
on_toggle: {
let client = client.read().clone();
let refresh_tasks = refresh_tasks.clone();
move |task_id: String| {
let client = client.clone();
let refresh_tasks = refresh_tasks.clone();
spawn(async move {
match client.toggle_scheduled_task(&task_id).await {
Ok(_) => {
show_toast("Task toggled".into(), false);
refresh_tasks();
}
Err(e) => show_toast(format!("Toggle failed: {e}"), true),
}
});
}
},
on_run_now: {
let client = client.read().clone();
let refresh_tasks = refresh_tasks.clone();
move |task_id: String| {
let client = client.clone();
let refresh_tasks = refresh_tasks.clone();
spawn(async move {
match client.run_scheduled_task_now(&task_id).await {
Ok(_) => {
show_toast("Task started".into(), false);
refresh_tasks();
}
Err(e) => show_toast(format!("Run failed: {e}"), true),
}
});
}
},
}
}
}
View::Settings => {
let cfg_ref = config_data.read();
match cfg_ref.as_ref() {